Dans un exemple, vous pouvez voir plusieurs filtres de requête OR:
Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))
Par exemple, cela se traduit par:
[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]
Cependant, je veux créer ce filtre de requête à partir d'une liste. Comment faire ça?
par exemple. [1, 2, 3] -> Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))
Vous pouvez chaîner vos requêtes comme suit:
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)
Pour construire des requêtes plus complexes, il est également possible d'utiliser les constantes Q.OR et Q.AND intégrées dans l'objet Q() avec la méthode add () comme suit:
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
Une façon plus courte d'écrire la réponse de Dave Webb en utilisant la fonction de réduction 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)
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))
Peut-être qu'il vaut mieux utiliser l'instruction SQL IN.
Article.objects.filter(id__in=[1, 2, 3])
Voir queryset api reference .
Si vous avez vraiment besoin de faire des requêtes avec une logique dynamique, vous pouvez faire quelque chose comme ça (moche + non testé):
query = Q(field=1)
for cond in (2, 3):
query = query | Q(field=cond)
Article.objects.filter(query)
Voir le 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([])
{}
Notez que cette méthode ne fonctionne que pour les recherches de clé primaire, mais cela semble être ce que vous essayez de faire.
Donc ce que vous voulez c'est:
Article.objects.in_bulk([1, 2, 3])
Si nous voulons définir par programme le champ de base de données à interroger:
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))
Vous pouvez utiliser l'opérateur | = pour mettre à jour une requête par programme à l'aide d'objets Q.
En utilisant la solution avec l'opérateur reduce
et or_
, comment filtrer par champs multiples.
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'{k}__in': v}) for k, v in filters.items()))
)
p.s. f
est un nouveau format de chaîne littéral aded en python3.6
Une autre option dont je n'étais pas au courant jusqu'à récemment - QuerySet
remplace également les opérateurs &
, |
, ~
, etc. Les autres réponses indiquent que les objets OR Q sont une meilleure solution à cette question, mais pour des raisons d’intérêt/argument, vous pouvez le faire:
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)
renverra une requête avec tous les filtres de la clause WHERE
.
Celui-ci est pour la liste dynamique de pk:
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)
facile..
depuis Django.db.models, importez Q importer votre modèle args = (Q (visibilité = 1) | (Q (visibilité = 0) & Q (utilisateur = self.user))) #Tuple paramètres = {} #dic order = 'create_at' limite = 10
Models.objects.filter(*args,**parameters).order_by(order)[:limit]