如何在Django中动态地向查询添加过滤器?

Ama*_*pta 5 python django django-orm

在我的viewSet中,我正在进行查询,

queryset= Books.objects.all();
Run Code Online (Sandbox Code Playgroud)

现在从ajax调用我从UI获得我的过滤器值,即auther的年龄,性别等.总共将有5个过滤器.

现在我遇到的问题是如何向查询添加过滤器(只有那些具有任何值的过滤器).

我尝试的是我检查了单个过滤器值并进行了查询,但这样就失败了,就像用户删除过滤器值或添加多个过滤器一样.任何更好的建议如何实现这一目标?

Ala*_*air 9

您没有显示任何代码,因此您还没有真正解释问题所在:

从查询集开始Book.objects.all().对于每个过滤器,检查过滤器中是否有值,如果有request.POST,则过滤查询集.Django查询集是惰性的,因此只会评估最终的查询集.

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'])
...
Run Code Online (Sandbox Code Playgroud)

  • 值得一提的是,只有在需要结果时才会对它们进行评估:) +1 anywho (2认同)

Ale*_*zov 9

这是一个更通用的.如果它们作为GET参数传递,它将对您的查询集应用过滤器.如果您正在进行POST呼叫,只需更改代码中的名称即可.

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
Run Code Online (Sandbox Code Playgroud)

请注意,您可以在过滤器的名称中使用查找表达式.例如,如果要过滤价格低于或等于过滤器中指定价格的图书,则可以将其price__lte用作过滤器名称.

  • 我正在尝试完全做到这一点,但它总是说“无法将关键字“过滤器”解析为字段”。任何的想法? (2认同)

小智 5

您可以简单地将 request.GET 内容作为 dict 获取(确保将值转换为字符串或所需类型,因为默认情况下它们是列表,即:dict(request.GET)会给您类似{u'a': [u'val']}.

一旦你确定你有一个匹配你的模型字段的键字典,你可以简单地做:

filtered = queryset.filter(**dict_container)