Filtro de Django base de datos para el campo que contiene cualquier valor en una matriz

Tengo un modelo de django y un campo que representa a un usuario de nombre completo. Mi cliente quiere establecer un filtro para buscar un usuario basado en una matriz de cadenas, donde todos ellos tienen que ser sensibles a mayúsculas y minúsculas contenida en el nombre completo.

Por ejemplo

Si los usuarios full_name = "Keith, Thomson S."

Y tengo una lista ['keith','s','thomson']

Quiero realizar el filtro equivalente de

Profile.objects.filter(full_name__icontains='keith',full_name__icontains='s',full_name__icontains='thomson')

El problema es que esta lista puede ser de la dinámica de tamaño, así que no sé cómo hacerlo.

Alguien tiene alguna idea?

OriginalEl autor xizor | 2012-01-20

3 respuestas

  1. 40

    Hacer llamadas sucesivas a filter, así:

    queryset = Profile.objects.all()
    strings = ['keith', 's', 'thompson']
    for string in strings:
        queryset = queryset.filter(full_name__icontains=string)

    Alternativamente, usted puede & juntos un montón de Q objetos:

    condition = Q(full_name__icontains=s[0])
    for string in strings[1:]:
        condition &= Q(full_name__icontains=string)
    queryset = Profile.objects.filter(condition) 

    Más críptico manera de escribir esto, evitando la explícita bucle:

    import operator
    # ...
    condition = reduce(operator.and_, [Q(full_name__icontains=s) for s in strings])
    queryset = Profile.objects.filter(condition)
    Me pregunto cuál es la final de la expresión sql se va a parecer después de que el encadenamiento de todos estos filtros.
    Acabo de probar (bueno, algo similar) — que se traduce a una serie de ANDs en el where cláusula, es decir, full_name LIKE %keith% AND full_name LIKE %s% AND ...
    tenga en cuenta que el operador predeterminado para múltiples objetos Q es Y por lo que sólo puede *[Q1, Q2, Q3] sin usar reducir / operador.and_.
    hace este trabajo sobre las claves principales. estoy teniendo problema similar, obj = ModelClass.objetos.filtro de(nombre de__contains(“substr”)) el nombre es una clave principal ?

    OriginalEl autor Ismail Badawi

  2. 8

    Aún más el uso de la operator funciones and_ o or_ combinar la lista de Q() condiciones

    from operator import and_, or_
    li = ['keith', 's', 'thompson']

    Los elementos que coinciden todas las cadenas (and_)

    Profile.objects.filter(reduce(and_, [Q(full_name__icontains=q) for q in li]))

    Los elementos que coinciden con alguna de las cadenas (or_)

    Profile.objects.filter(reduce(or_, [Q(full_name__icontains=q) for q in li]))

    La Q() función implementa __or__() y __and__() para unir dos Q() objetos juntos, por lo que puede ser llamado mediante el correspondiente operator funciones.

    OriginalEl autor C14L

  3. 2

    algo a lo largo de estas líneas:

    
    array = ['keith', 's', 'thomson']
    regex = '^.*(%s).*$' % '|'.join(array)
    Profile.objects.filter(full_name__iregex=regex)

    EDIT: esto está mal, el OP quiere nombres que contienen todas las cadenas simultáneamente.

    OriginalEl autor akonsu

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *