Django: Query using contains each value in a list
DjangoDjango ModelsDjango Problem Overview
I need to perform a django query that checks if a field contains all values within a list. The list will be of varying length
Example
User.objects.filter(first_name__contains=['x','y','z'])
Django Solutions
Solution 1 - Django
import operator
from django.db.models import Q
User.objects.filter(reduce(operator.and_, (Q(first_name__contains=x) for x in ['x', 'y', 'z'])))
for python 3
from functools import reduce
.
Solution 2 - Django
import operator
from django.db.models import Q
q = ['x', 'y', 'z']
query = reduce(operator.and_, (Q(first_name__contains = item) for item in q))
result = User.objects.filter(query)
Solution 3 - Django
Just another approach.
qs = User.objects.all()
for search_term in ('x', 'y', 'z'):
qs = qs.filter(first_name__contains=search_term)
I'm not sure if it is better, but it's more readable.
Note: Querysets are lazy, so this code makes 1 DB query.
Solution 4 - Django
from django.db.models import Q
User.objects.filter(Q(first_name__contains=x)&Q(first_name__contains=y)&Q(first_name__contains=z))
Works for me on Django 1.8 python 2.7
doc => https://docs.djangoproject.com/en/1.8/ref/models/querysets/#q-objects
for more recent => https://docs.djangoproject.com/en/2.1/ref/models/querysets/#q-objects
Solution 5 - Django
The accepted solution didn't work for me, but this did:
list = ['x', 'y', 'z']
results = User.objects.filter(first_name__contains=list[0])
del list[0]
for l in list:
results = results.filter(first_name__contains=l)
The first results variable will store a list of all the objects with the first_name name field value 'x'.
And then in the for loop you filter for 'y' amongst the first filter results. Now you have a QuerySet that should contain a list of items where both 'x' and 'y' can be found. Now amongst those you filter for any item that contains 'z' as well.
This should work for any length list.
Solution 6 - Django
It doesn't apply exactly here, but, if you have a ManyToManyField
and you want to check if it contains a specific value, check this https://www.revsys.com/tidbits/tips-using-djangos-manytomanyfield/.
I have a "Products" and Django native "Users" model. My "Products" model has a many-to-many field users
pointing to "Users". Then, I wanted to check if this list-like field contained the logged in user. I did that by ...users__username_icontains=request.user.username...
and the link above helped me to understand better what is a many-to-many field and how it works.
Solution 7 - Django
the_list= []
data_list= ['x', 'y', 'z']
for i in data_list:
a = User.objects.filter(first_name__contains=project).values('etc')
the_list+= a
Solution 8 - Django
This worked for me in django 2.2, python 3.8, using lambda instead of 'operator'. Explanations on lambda can be found here: https://www.python-course.eu/lambda.php
from functools import reduce
from django.db.models import Q
my_list = ['x','y','z']
User.objects.filter(reduce(lambda x, y: x & y, [Q(first_name__contains= i for i in my_list]))