首页 > 解决方案 > 如何使用 django-filter 构建过滤器类,允许通过一个模型字段的多个值进行查询

问题描述

我必须构建必须允许按多个值过滤的端点。它必须看起来像这样:

http://example.com/page?field=1&field=2&filed=3

可以说这field是一个IntegFieldMyModel我想通过 this 中的任何值进行查询field

我想执行这样或类似的查询 + 验证查询参数列表

MyModel.objects.filter(field__in=[1,2,3])

django-filter( https://django-filter.readthedocs.io/en/stable/ ) 库看起来很有希望,但在文档中我还没有找到一种简单的方法来做这么简单的事情。我怎样才能做到这一点?

验证也很重要。我不想允许使用这样的参数执行查询field=yolo

到目前为止,我得到了不支持验证的代码

import django_filters as df
from django.forms.widgets import SelectMultiple
    

class MyFilter(df.FilterSet):
    id = df.Filter(required=False, field_name="id", widget=SelectMultiple(), lookup_expr="in")

    class Meta:
        model = MyModel
        fields = ["id"]

标签: djangodjango-filterquery-parameters

解决方案


也许不是最优雅的方式,但这就是我实现目标的方式:

from django_filters.fields import BaseCSVField
from django_filters.widgets import QueryArrayWidget

class MyBaseCSVField(BaseCSVField):
    base_widget_class = QueryArrayWidget


class MyBaseInFilter(df.BaseInFilter):
    base_field_class = MyBaseCSVField


class NumberInFilter(MyBaseInFilter, df.NumberFilter):
    pass


class MytFilter(df.FilterSet):
    field = NumberInFilter()

    class Meta:
        modem = MyModel
        fields = ("field", )

所以这里的关键是QueryArrayWidget来自docstrin的and:

 1. Values can be provided as csv string:  ?foo=bar,baz
 2. Values can be provided as query array: ?foo[]=bar&foo[]=baz
 3. Values can be provided as query array: ?foo=bar&foo=baz

一般来说,这个库在我的诚实意见中没有得到很好的记录。


推荐阅读