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)
Esto podría ser útil https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships
Básicamente suena como que actúan como O
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.