python - latest - tutorial django
¿Cómo redactar dinámicamente un filtro de consulta OR en Django? (12)
En caso de que deseamos establecer programáticamente qué campo db queremos consultar:
import operator
questions = [(''question__contains'', ''test''), (''question__gt'', 23 )]
q_list = [Q(x) for x in questions]
Poll.objects.filter(reduce(operator.or_, q_list))
De un ejemplo, puede ver un filtro O de consulta múltiple:
Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))
Por ejemplo, esto da como resultado:
[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]
Sin embargo, quiero crear este filtro de consulta de una lista. ¿Como hacer eso?
por ejemplo [1, 2, 3] -> Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))
Este es para la lista de pk dinámica:
pk_list = qs.values_list(''pk'', flat=True) # i.e [] or [1, 2, 3]
if len(pk_list) == 0:
Article.objects.none()
else:
q = None
for pk in pk_list:
if q is None:
q = Q(pk=pk)
else:
q = q | Q(pk=pk)
Article.objects.filter(q)
Otra opción que no conocía hasta hace poco: QuerySet
también anula el &
, |
, ~
, etc, operadores. Las otras respuestas que los objetos OR Q son una mejor solución a esta pregunta, pero por el bien de interés / argumento, puede hacer:
id_list = [1, 2, 3]
q = Article.objects.filter(pk=id_list[0])
for i in id_list[1:]:
q |= Article.objects.filter(pk=i)
str(q.query)
devolverá una consulta con todos los filtros en la cláusula WHERE
.
Para crear consultas más complejas, también existe la opción de usar las constantes del objeto Q () Q.OR y Q.AND junto con el método add () como sigue:
list = [1, 2, 3]
# it gets a bit more complicated if we want to dynamically build
# OR queries with dynamic/unknown db field keys, let''s say with a list
# of db fields that can change like the following
# list_with_strings = [''dbfield1'', ''dbfield2'', ''dbfield3'']
# init our q objects variable to use .add() on it
q_objects = Q()
# loop trough the list and create an OR condition for each item
for item in list:
q_objects.add(Q(pk=item), Q.OR)
# for our list_with_strings we can do the following
# q_objects.add(Q(**{item: 1}), Q.OR)
queryset = Article.objects.filter(q_objects)
# sometimes the following is helpful for debugging (returns the SQL statement)
# print queryset.query
Puede encadenar sus consultas de la siguiente manera:
values = [1,2,3]
# Turn list of values into list of Q objects
queries = [Q(pk=value) for value in values]
# Take one Q object from the list
query = queries.pop()
# Or the Q object with the ones remaining in the list
for item in queries:
query |= item
# Query the model
Article.objects.filter(query)
Puede usar el operador | = para actualizar programáticamente una consulta utilizando objetos Q.
Tal vez es mejor usar la instrucción SQL IN.
Article.objects.filter(id__in=[1, 2, 3])
Ver la referencia de queryset api .
Si realmente necesita realizar consultas con lógica dinámica, puede hacer algo como esto (feo + no probado):
query = Q(field=1)
for cond in (2, 3):
query = query | Q(field=cond)
Article.objects.filter(query)
Una forma más corta de escribir la respuesta de Dave Webb usando la función de reducción de Python :
# For Python 3 only
from functools import reduce
values = [1,2,3]
# Turn list of values into one big Q objects
query = reduce(lambda q,value: q|Q(pk=value), values, Q())
# Query the model
Article.objects.filter(query)
Usando la solución con reduce
y or_
operador aquí, ¿cómo se puede filtrar por campos de multiplicación?
from functools import reduce
from operator import or_
from django.db.models import Q
filters = {''field1'': [1, 2], ''field2'': [''value'', ''other_value'']}
qs = Article.objects.filter(
reduce(or_, (
Q(**{f''{field}__in'': list_filters[field]})
for field in list_filters
)
)
)
ps f
es un nuevo formato cadenas literal aded en python3.6
Ver los docs :
>>> Blog.objects.in_bulk([1])
{1: <Blog: Beatles Blog>}
>>> Blog.objects.in_bulk([1, 2])
{1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>}
>>> Blog.objects.in_bulk([])
{}
Tenga en cuenta que este método solo funciona para búsquedas de claves primarias, pero parece ser lo que intenta hacer.
Entonces lo que quieres es:
Article.objects.in_bulk([1, 2, 3])
fácil..
desde django.db.models importa Q importa tu modelo args = (Q (visibility = 1) | (Q (visibility = 0) & Q (user = self.user))) #Tuple parameters = {} #dic order = ''create_at ''límite = 10
Models.objects.filter(*args,**parameters).order_by(order)[:limit]
from functools import reduce
from operator import or_
from django.db.models import Q
values = [1, 2, 3]
query = reduce(or_, (Q(pk=x) for x in values))