variable tutorial template examples custom django django-queryset

tutorial - inclusion tags django



Filtros Django-o? (6)

¿Cómo haría un "o" en un filtro django.

Básicamente, quiero poder listar los elementos que un usuario ha agregado (están listados como el creador) o el elemento ha sido aprobado

así que básicamente necesito seleccionar

item.creator = owner or item.moderated = False

Cómo haría esto en django (preferiblemente con un filtro / queryset)



Hay objetos Q que permiten búsquedas complejas. Ejemplo:

from django.db.models import Q Item.objects.filter(Q(creator=owner) | Q(moderated=False))


Puedes usar el | Operador para combinar querysets directamente sin necesidad de objetos Q:

result = Item.objects.filter(item.creator = owner) | Item.objects.filter(item.moderated = False)

(Editar: inicialmente no estaba seguro de si esto causaba una consulta adicional, pero @spookylukey señaló que la evaluación perezosa de consultas se encarga de eso)


Quieres hacer el filtro dinámico, entonces tienes que usar Lambda como

from django.db.models import Q brands = [''ABC'',''DEF'' , ''GHI''] queryset = Product.objects.filter(reduce(lambda x, y: x | y, [Q(brand=item) for item in brands]))

reduce(lambda x, y: x | y, [Q(brand=item) for item in brands]) es equivalente a

Q(brand=brands[0]) | Q(brand=brands[1]) | Q(brand=brands[2]) | .....


Similar a la respuesta anterior, pero un poco más simple, sin la lambda:

filter_kwargs = { ''field_a'': 123, ''field_b__in'': (3, 4, 5, ), }

Para filtrar estas dos condiciones utilizando OR :

Item.objects.filter(Q(field_a=123) | Q(field_b__in=(3, 4, 5, ))

Para obtener el mismo resultado programáticamente:

list_of_Q = [Q(**{key: val}) for key, val in filter_kwargs.items()] Item.objects.filter(reduce(operator.or_, list_of_Q))

(roto en dos líneas aquí, para mayor claridad)

operator está en la biblioteca estándar: import operator
Desde docstring:

or_ (a, b) - Igual que a | segundo.

Para Python3, reducir no está en la biblioteca estándar: from functools import reduce

PD

No olvide asegurarse de que list_of_Q no esté vacío: reduce() se ahogará en la lista vacía, necesita al menos un elemento.


Vale la pena tener en cuenta que es posible agregar expresiones Q.

Por ejemplo:

from django.db.models import Q query = Q(first_name=''mark'') query.add(Q(email=''[email protected]''), Q.OR) query.add(Q(last_name=''doe''), Q.AND) queryset = User.objects.filter(query)

Esto termina con una consulta como:

(first_name = ''mark'' or email = ''[email protected]'') and last_name = ''doe''

De esta manera no hay necesidad de tratar con operadores, reductores, etc.