How To Add Filters To A Query Dynamically In Django?
Solution 1:
Here's a bit more generic one. It will apply filters to your queryset if they are passed as the GET
parameters. If you're doing a POST
call, just change the name in the code.
import operator
from django.db.models import Q
defyour_view(self, request, *args, **kwargs):
# Here you list all your filter names
filter_names = ('filter_one', 'filter_two', 'another_one', )
queryset = Books.objects.all();
filter_clauses = [Q(filter=request.GET[filter])
forfilterin filter_names
if request.GET.get(filter)]
if filter_clauses:
queryset = queryset.filter(reduce(operator.and_, filter_clauses))
# rest of your view
Note that you can use lookup expressions in your filters' names. For example, if you want to filter books with price lower or equal to specified in filter, you could just use price__lte
as a filter name.
Solution 2:
You haven't shown any code, so you haven't really explained what the problem is:
Start with the queryset Book.objects.all()
. For each filter, check if there is a value for the filter in request.POST
, and if so, filter the queryset. Django querysets are lazy, so only the final queryset will be evaluated.
queryset = Book.objects.all()
if request.POST.get('age'):
queryset = queryset.filter(author__age=request.POST['age'])
if request.POST.get('gender'):
queryset = queryset.filter(author__gender=request.POST['gender'])
...
Solution 3:
You can simply get the request.GET content as a dict (making sure to convert the values to string or a desired type as they'd be list by default i.e: dict(request.GET)
would give you something like {u'a': [u'val']}
.
Once you are sure you have a dictionary of keys matching your model fields, you can simply do:
filtered = queryset.filter(**dict_container)
Solution 4:
Maybe django-filter would help simplify the solutions others have given?
Something like:
classBookFilter(django_filters.FilterSet):
classMeta:
model = Bookfields= ['author__age', 'author__gender', ...]
Then the view looks like:
defbook_list(request):
f = BookFilter(request.GET, queryset=Book.objects.all())
return render_to_response('my_app/template.html', {'filter': f})
For more information see the documentation.
Solution 5:
this worked for me, I've merged Alex Morozov answer with Dima answer
import operator
defyour_view(self, request, *args, **kwargs):
# Here you list all your filter names
filter_names = ('filter_one', 'filter_two', 'another_one', )
queryset = Books.objects.all();
filter_clauses = [Q(**{filter: request.GET[filter]})
forfilterin filter_names
if request.GET.get(filter)]
if filter_clauses:
queryset = queryset.filter(reduce(operator.and_, filter_clauses))
# rest of your view
Post a Comment for "How To Add Filters To A Query Dynamically In Django?"