在django_filter中,按值列表过滤仍然过于复杂,并且,通过扩展,Django Rest Framework(DRF)或者我错过了一些简单的东西,这是否正确?
具体来说,当我们处理通过URL提交的多值参数时,我们必须先使用'getlist'而不是'get'来指定应该处理的参数:
http://example.com?country=US&country=CN
现在,当我们处理此请求时,
在请求时,request.query_params.get('country')以及 request.query_params ['country'] 将错误地返回'CN'。 query_params.getlist('country')
将返回['US','CN'],这是我们在此示例中所希望的。所以我当前的逻辑规定我必须提前指定哪些参数可能指定了多个值,因为我不知道一个透明处理这个参数的内部方法:
所以为了解决这个问题,我现在做了类似的事情(为了简单起见,跳过所有实际的请求处理,过滤等):
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')
理论上,filter1应该给我想要的结果,而filter0则不会。
基于此的代码在我的生产环境中有效,但还有一些其他效果,例如将有效列表转换回字符串。我不想在这里提出这个问题,只是想知道这是否是人们做的事情?
答案 0 :(得分:0)
具体而言,我们必须先指定应使用' getlist'处理的参数。而不是与'得到'当我们处理通过URL提交的多值参数时,如下所示:
这不是必需的。 Filter
个实例构造一个表单字段,然后执行查询参数验证。这些字段是标准的Django表单字段,其小部件将决定在从查询字典中提取值时是否使用.getlist()
或.get()
。您不需要预处理查询字典。
在您的示例中,filter0和filter1实际上应该具有相同的行为,因为QueryDict('a=1&a=2')
在功能上等同于dict(a=['1', '2'])
小部件的SelectMultiple
。其.value_from_datadict()
会在前者上调用.getlist()
,在后者调用.get()
- 两者都会返回值列表。
关于解决多个值过滤的问题,您有两个选择。
MultipleChoiceFilter
(docs)多选过滤器会呈现一个选择多个窗口小部件,并且需要一个像?a=1&a=b
这样的查询字符串。您尝试了上述操作,但省略了choices
。没有选择,html选择将在没有选项的情况下呈现,验证将随后失败(因为它使用相同的选项来验证输入)。或者,您可以使用ModelMultipleChoiceFilter
,这需要queryset
来构建其选择。请注意,查询集/选择处理是底层表单字段的内置行为,并不是django-filter特有的。
对于后一个选项,上面链接的文档中有更多详细信息,但值得一提的是,它会呈现文本输入,并且需要?a=1,2
而不是?a=1&a=2
这样的查询字符串。