How to dynamically compose an OR query filter in Django?
You could chain your queries as follows:
values = [1,2,3]# Turn list of values into list of Q objectsqueries = [Q(pk=value) for value in values]# Take one Q object from the listquery = queries.pop()# Or the Q object with the ones remaining in the listfor item in queries: query |= item# Query the modelArticle.objects.filter(query)
To build more complex queries there is also the option to use built in Q() object's constants Q.OR and Q.AND together with the add() method like so:
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 itq_objects = Q(id__in=[])# loop trough the list and create an OR condition for each itemfor 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
A shorter way of writing Dave Webb's answer using python's reduce function:
# For Python 3 onlyfrom functools import reducevalues = [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)