Django-filter多个URL参数

7 投票
3 回答
16915 浏览
提问于 2025-04-18 16:32

我正在使用Django-filter这个应用程序来在我的网站上构建搜索功能。以下是我的代码:

class PropertyFilter(django_filters.FilterSet):
city = django_filters.ModelMultipleChoiceFilter(queryset=City.objects.all(), widget = CheckboxSelectMultiple)
trade_type = django_filters.ModelMultipleChoiceFilter(queryset=Trade.objects.all(), widget = CheckboxSelectMultiple)

class Meta:
    model = Property
    fields = ['city', 'trade_type']

问题是,当用户选择了两个城市时,Django-filter只会根据最后一个城市的参数来过滤数据(在这个例子中是城市编号2):

http://example.org/lt/list/city=1&city=2

Models.py

class City(models.Model):
    name = models.CharField(max_length=250, verbose_name=_('Name'))

我是不是哪里做错了呢?

3 个回答

1

最好的方法是使用来自 Django filter 文档 的自定义过滤器。在我的情况下,我使用了 (',') 来分隔网址,应该看起来像这样:

localhost:8000/?city=1,2,3(你可以使用字符串值)

    
   class F(django_filters.FilterSet):
         city = CharFilter(method='my_custom_filter')

         class Meta:
            model = Property
            fields = ['city','trade_type']

         def my_custom_filter(self, queryset, name, value):
            value_list = value.split(u',') #split the values by ,
            return queryset.filter(**{
            name+"__in": value_list, #add __in to get each value of the list
            })
2

你可以用你之前尝试的那个网址来实现这个功能。跟着我的例子走就行。你需要传递你想要过滤的选项。

我调用的网址是:

http://example.org/product-list/gender=1&gender=2

filters.py

GENDER_CHOICES = tuple(
    ProductAttributeOptions.objects.filter(group__name='gender').values_list('id', 'option'))

class ProductFilter(django_filters.FilterSet):        
    gender = django_filters.MultipleChoiceFilter(choices=GENDER_CHOICES,
                                                 method='filter_gender')

    def filter_gender(self, qs, name, value):
        result = qs.filter(Q(attribute_values__attribute__name='gender',
                         attribute_values__value_option__in=value))

        return result

class Meta:
    model = Product
    fields = ('gender')

希望这能帮到你。我参考了官方文档

7

你可以创建一个复数形式的查询字符串,并接受一个列表作为过滤参数:

http://example.org/lt/list/?cities=1,2


class CustomFilterList(django_filters.Filter):
    def filter(self, qs, value):
        if value not in (None, ''):
            values = [v for v in value.split(',')]
            return qs.filter(**{'%s__%s' % (self.name, self.lookup_type): values})
        return qs

class PropertyFilter(django_filters.FilterSet):
    city = django_filters.ModelMultipleChoiceFilter(queryset=City.objects.all(), widget = CheckboxSelectMultiple)
    trade_type = django_filters.ModelMultipleChoiceFilter(queryset=Trade.objects.all(), widget = CheckboxSelectMultiple)
    cities = CustomFilterList(name="city", lookup_type="in")

    class Meta:
        model = Property
        fields = ['cities', 'city', 'trade_type']

可以查看这个回答,了解如何正确过滤一系列值:

是否可以通过django-filter的URL解析器进行`in` `lookup_type`?

撰写回答