Django 过滤器:单个查询字符串中的多个 ID

mar*_*t1n 5 django django-filter django-rest-framework

使用django-filters,我看到了如何在单个查询字符串中提交多个相同类型参数的各种解决方案,例如多个 ID。他们都建议使用包含逗号分隔值列表的单独字段,例如:

http://example.com/api/cities?ids=1,2,3
Run Code Online (Sandbox Code Playgroud)

是否有使用单个参数但提交一次或多次的通用解决方案?例如:

http://example.com/api/cities?id=1&id=2&id=3
Run Code Online (Sandbox Code Playgroud)

我尝试使用MultipleChoiceFilter,但它期望定义实际选择,而我想传递任意 ID(其中一些甚至可能不存在于数据库中)。

Ser*_*nov 7

作为选项

class CityFilterSet(django_filters.FilterSet):
    id = django_filters.NumberFilter(method='filter_id')

    def filter_id(self, qs, name, value):
        return qs.filter(id__in=self.request.GET.getlist('id'))

Run Code Online (Sandbox Code Playgroud)


Ben*_*hon 5

这是一个使用customFilter和 custom的可重用解决方案Field

自定义Field重用 Django 的MultipleChoiceField但替换了验证函数。相反,它使用Field我们传递给构造函数的另一个类进行验证。

from django.forms.fields import MultipleChoiceField

class MultipleValueField(MultipleChoiceField):
    def __init__(self, *args, field_class, **kwargs):
        self.inner_field = field_class()
        super().__init__(*args, **kwargs)

    def valid_value(self, value):
        return self.inner_field.validate(value)

    def clean(self, values):
        return values and [self.inner_field.clean(value) for value in values]
Run Code Online (Sandbox Code Playgroud)

自定义Filter使用MultipleValueField并转发field_class参数。它还设置了默认值lookup_exprto in

from django_filters.filters import Filter

class MultipleValueFilter(Filter):
    field_class = MultipleValueField

    def __init__(self, *args, field_class, **kwargs):
        kwargs.setdefault('lookup_expr', 'in')
        super().__init__(*args, field_class=field_class, **kwargs)
Run Code Online (Sandbox Code Playgroud)

要使用此过滤器,只需MultipleValueFilter使用适当的field_class. 例如,要过滤Cityid,我们可以用一个IntegerField,就像这样:

from django.forms.fields import IntegerField

class CityFilterSet(FilterSet):
    id = MultipleValueFilter(field_class=IntegerField)
    name = filters.CharFilter(lookup_expr='icontains')

    class Meta:
        model = City
        fields = ['name']
Run Code Online (Sandbox Code Playgroud)