Django / GET 表单 / Q 过滤

Posted

技术标签:

【中文标题】Django / GET 表单 / Q 过滤【英文标题】:Django / GET form / Q filtering 【发布时间】:2014-06-20 09:37:21 【问题描述】:

我正在尝试为我的结果创建过滤器,该过滤器将从 html 表单中获取多个值。 当前的设置为我提供了诸如 /?language=French&language=German 之类的 URL,但是结果不会显示法语和德语记录,而只会显示法语。此外,添加新的过滤条件,例如 "level" /?language=French&level=Beginner 也不起作用。

有人可以帮我指出正确的方向吗?

谢谢 西科尔

我的表格如下:

RESOURCES_LANGUAGE =        (('English', 'English'),
                            ('Spanish', 'Spanish'),
                            ('French', 'French'),
                            ('German', 'German'))

RESOURCES_LEVEL =           (('Beginner', 'Beginner'),
                            ('Intermediate', 'Intermediate'),
                            ('Advanced', 'Advanced'))

SORTBY =                    (('likes', 'Likes'),
                            ('name', 'Name'),
                            ('latest', 'Latest'))

class FiltersAndSortingForm(forms.Form): 
    language = forms.MultipleChoiceField(required=False, label='Language', widget=forms.CheckboxSelectMultiple, choices=RESOURCES_LANGUAGE)
    level = forms.MultipleChoiceField(required=False, label='Level', widget=forms.CheckboxSelectMultiple, choices=RESOURCES_LEVEL)
    provider = forms.ModelMultipleChoiceField(queryset=Provider.objects.all().order_by('name'), label='Provider', required=False,)
    sortby = forms.MultipleChoiceField(required=False, label='Sort by', widget=forms.CheckboxSelectMultiple, choices=SORTBY)

我的看法:

def resources(request):
    if request.GET:
        language = request.GET.get('language', '')
        level = request.GET.get('level', '')
        provider = request.GET.get('provider', '')  

        sortby = request.GET.get('sortby', '')
        if sortby == 'name':
            orderby = 'name'
        elif sortby == 'latest':
            orderby = '-dt_added'
        elif sortby == 'likes':
            orderby = '-facebook_likes'
        else:
            orderby = '-facebook_likes'    

        qset = (
            Q(language=language) 
#            & 
#            Q(level=level) 
            )

        resources = Resource.objects.filter(inactive=0).filter(qset).order_by(orderby)
        form = FiltersAndSortingForm()
    else:
        form = FiltersAndSortingForm()
        resources = Resource.objects.filter(inactive=0).order_by('-facebook_likes')

【问题讨论】:

好吧,filter(Q(language="French")&Q(level="Beginner")) 如果有既是法语又是初学者的资源,绝对应该可以工作。我会在你测试的地方删除一些东西,并验证这样的硬编码行是否有效...... 另外,您提到的 language=french&language=german 仅返回法语。这是您想要的还是您遇到的另一个问题? 这就是问题所在。每个对象在模型中只有一种语言。在这里,我想在一个组合结果中返回带有法语的对象列表和带有德语的对象列表,但是当前的设置并没有给我。看起来它忽略了第一个参数之后的所有内容 【参考方案1】:

我没有看到其他标准被添加到 qset,这就是过滤不适用于这些参数的原因。另外,我建议您使用字典作为搜索条件,然后将其解压缩。查看此问题以获取详细说明Django: How do I use a string as the keyword in a Q() statement?。如果您需要任何澄清,请告诉我。

【讨论】:

我明白你的意思,但我仍在努力将它准确地翻译成我的案例。你介意在这里多帮忙吗? 我现在清楚的一件事是语言实际上是一个列表,所以我需要有 language = request.GET.getlist('language', '') 但是我现在如何将这些值中的每一个放入我的 qset 中? 是的,没错。列表的长度等于特定选择字段的选中复选框的数量。【参考方案2】:

好的,最终在查看了这个帖子django dynamically filtering with q objects 之后,我得到了它的工作方式。也许这不是最干净的方式,但似乎它正在完成这项工作。除非有人能提出更好的解决方案?

谢谢 -s

def resources(request):
    if request.GET:
        type = request.GET.getlist('type', '')
        language = request.GET.getlist('language', '')
        level = request.GET.getlist('level', '')
        provider = request.GET.getlist('provider', '')  

        sortby = request.GET.get('sortby', '')
        if sortby == 'name':
            orderby = 'name'
        elif sortby == 'latest':
            orderby = '-dt_added'
        elif sortby == 'likes':
            orderby = '-facebook_likes'
        else:
            orderby = '-facebook_likes'  

        qset_type = Q() # Create an empty Q object to start with
        for x in type:
            qset_type |= Q(provider__tags__name=x) # 'or' the Q objects together

        qset_language = Q() 
        for x in language:
            qset_language |= Q(language=x) 

        qset_level = Q() 
        for x in level:
            qset_level |= Q(level=x) 

        qset_provider = Q() 
        for x in provider:
            qset_provider |= Q(provider=x)    

        qset = qset_language & qset_level & qset_type & qset_provider

        resources = Resource.objects.filter(inactive=0).filter(qset).order_by(orderby)
        form = FiltersAndSortingForm()
    else:
        form = FiltersAndSortingForm()
        resources = Resource.objects.filter(inactive=0).order_by('-facebook_likes')

【讨论】:

以上是关于Django / GET 表单 / Q 过滤的主要内容,如果未能解决你的问题,请参考以下文章

Django 从模型中过滤:Model.objects.filter(Q())

使用多选表单在 DJANGO 中过滤

如何在 django 中过滤多条消息

PythonDjango filter 如何支持 or 条件过滤?

Django过滤查询和或

Django,按用户全名过滤 Q 对象