How to add filters to a query dynamically in Django?

牧云@^-^@ 提交于 2019-12-21 05:08:02

问题


In my viewSet I am doing a query,

queryset= Books.objects.all();

Now from an ajax call I get my filter values from UI i.e. age,gender, etc. of auther.There will be a total of 5 filters.

Now the problem which I ran into is how am I going to add filters to my query(only those filters which have any value).

What I tried is I checked for individual filter value and did query, but that way it fails as if the user remove the filter value or add multiple filters. Any better suggestion how to accomplish this?


回答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


def your_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])
                      for filter in 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.




回答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'])
...



回答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)




回答4:


Maybe django-filter would help simplify the solutions others have given?

Something like:

class BookFilter(django_filters.FilterSet):
    class Meta:
        model = Book
        fields = ['author__age', 'author__gender', ...]

Then the view looks like:

def book_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.




回答5:


this worked for me, I've merged Alex Morozov answer with Dima answer

import operator

def your_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]})
                  for filter in filter_names
                  if request.GET.get(filter)]
if filter_clauses:
    queryset = queryset.filter(reduce(operator.and_, filter_clauses))

# rest of your view



回答6:


You can do something like that

class BooksAPI(viewsets.ModelViewSet):
    queryset = Books.objects.none()


def get_queryset(self):
    argumentos = {}
    if self.request.query_params.get('age'):
        argumentos['age'] = self.request.query_params.get('age')
    if self.request.query_params.get('gender'):
        argumentos['gender'] = self.request.query_params.get('gender')
    if len(argumentos) > 0:
        books = Books.objects.filter(**argumentos)
    else:
        books = Books.objects.all()
    return books


来源:https://stackoverflow.com/questions/34739680/how-to-add-filters-to-a-query-dynamically-in-django

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!