Django rest framework django_过滤器django Rest框架(DRF)处理查询参数get vs getlist

Django rest framework django_过滤器django Rest框架(DRF)处理查询参数get vs getlist,django-rest-framework,django-filter,Django Rest Framework,Django Filter,在django_过滤器和django Rest框架(DRF)中,通过值列表进行过滤仍然过于复杂,这是正确的吗?还是我缺少了一些简单的东西 具体来说,当我们处理通过URL提交的多值参数时,我们必须预先指定应使用“getlist”而不是“get”处理的参数,如下所示: 现在,当我们处理这个请求时 request.query_-params.get('country')以及request.query_-params['country']将错误地返回'CN',而request.query_-param

在django_过滤器和django Rest框架(DRF)中,通过值列表进行过滤仍然过于复杂,这是正确的吗?还是我缺少了一些简单的东西

具体来说,当我们处理通过URL提交的多值参数时,我们必须预先指定应使用“getlist”而不是“get”处理的参数,如下所示:

现在,当我们处理这个请求时

request.query_-params.get('country')以及request.query_-params['country']将错误地返回'CN',而request.query_-params.getlist('country')将返回['US','CN',这就是我们在本例中希望的结果

因此,我当前的逻辑要求我必须提前指定哪些参数可能指定了多个值,因为我不知道有哪种内部方法可以透明地处理这些值:

因此,为了处理这个问题,我目前做了一些类似的事情(为了简单起见,跳过所有实际的请求处理、过滤等):

从理论上讲,filter1应该提供所需的结果,而filter0不会

基于此的代码在我的生产环境中工作,但也有一些其他效果,如将有效列表转换回字符串。我不想在这里陷入这个问题,只是想知道这是否是人们所做的

具体来说,当我们处理通过URL提交的多值参数时,我们必须预先指定应使用“getlist”而不是“get”处理的参数,如下所示:

这是没有必要的<代码>过滤器实例构造一个表单字段,该字段依次执行查询参数验证。这些字段是标准的Django表单字段,其小部件将确定从查询dict提取值时是否使用
.getlist()
.get()
。您不需要预处理查询dict

在您的示例中,filter0和filter1的行为实际上应该是相同的,因为
QueryDict('a=1&a=2')
在功能上等同于
dict(a=['1','2'))
对于
选择多个
小部件。它将对前者调用
.getlist()
,对后者调用
.get()
——两者都将返回一个值列表


至于解决按多个值过滤的问题,您有两个选择

  • 使用
    多回音滤镜
    ()
  • 使用基于CSV的筛选器()
  • 多选过滤器呈现一个selectmultiplewidget,并需要一个类似
    ?a=1&a=b
    的查询字符串。您尝试了上述操作,但忽略了
    选项
    。如果没有选项,html select将在没有选项的情况下呈现,验证随后将失败(因为它使用这些相同的选项来验证输入)。或者,您可以使用,它需要
    queryset
    来构造其选项。请注意,queryset/choice处理是基础表单字段的内置行为,并不特定于django筛选器

    对于后一个选项,上面链接的文档中有更多详细信息,但值得一提的是,它呈现一个文本输入,并需要一个类似
    ?a=1,2
    的查询字符串,而不是
    ?a=1&a=2

    class CountryFilter(filters.FilterSet):
         """ placeholder: this is a separate question as to why I can't get any of these to work as desired. """
         #country = filters.CharFilter(method='filter_country')
         #country = filters.CharFilter(name='country', lookup_expr='in')
         #country = filters.MultipleChoiceFilter()
    
    class CountryViewSet(viewsets.ModelViewSet):
        """Viewset to work with countries by ISO code"""
    
        def list(self, request, *args, **kwargs):
            """do something based on a request for one or more countries
            such as http://example.com?country=CA&country=CN&country=BR
            """
            query_params = request.query_params
            filter0 = CountryFilter(query_params, queryset=Country.objects.all())       
    
            # if filter0 worked, we'd be done and wouldn't need below
            # but it doesn't
    
            query_dict = {}
            params_to_list = ['country', 'another_param']
            for k in query_params.keys():
                if k in params_to_list:
                    query_dict[k] = query_params.getlist(k)
                else:
                    query_dict[k] = query_params.get(k)
    
            # use the newly counstructed query_dict rather than query_params
            filter1 = CountryFilter(query_dict, queryset=Country.objects.all())
    
            import pdb; pdb.set_trace()
            return HttpResponse('ok')