【问题标题】:django-filter: only show filter options contained in querysetdjango-filter:仅显示查询集中包含的过滤器选项
【发布时间】:2018-04-28 11:58:56
【问题描述】:

我正在使用出色的 django-filter 应用程序来过滤模型对象的查询集。但是,当我从视图中的查询集中 .exclude() 对象时,模板中的过滤器选择器仍然显示所有可用选项——即使是我从查询集中排除的对象。假设我的模型和视图如下所示:

#model
[...]
class Animal(models.Model):
    REGION_CHOICES = (
        (0, 'Africa'),
        (1, 'Europe'),
    )

    name = models.CharField(max_length=100)
    region = models.CharField(choices=REGION_CHOICES, max_length=100)
[...]

#view  
[...]  
qs = Animal.objects.all()
filter = AnimalFilter(request.GET, qs)
[...]

假设数据库中有两种动物:

zebra = Animal(name='Zebra', region='Africa')
frog = Animal(name='Frog', region'Europe')

当我在模板中渲染过滤器时,我正确地获得了一个包含欧洲和非洲两个选项的区域选择器。 但是,如果我在视图中使用一些逻辑来 .exclude() 查询集中的对象,如下所示:

#view
[...]
qs = Animal.objects.all().exclude(name='Frog')
filter = AnimalFilter(request.GET, qs)
[...]

现在,如果我在模板中渲染过滤器,我仍然会得到两个选项 EuropeAfrica 用于区域,尽管查询集只包含一种具有区域 非洲。 任何想法如何获得模板中呈现的区域字段的正确选项?非常感谢任何帮助。

【问题讨论】:

    标签: django django-filter django-filters


    【解决方案1】:

    您可以覆盖FilterSet.__init__() 中的choices,以确保区域选择仅限于基于提供的查询集的区域。

    class AnimalFilter(FilterSet):
        def __init__(self, *args, **kwargs):
            super(AnimalFilter, self).__init__(*args, **kwargs)
    
            regions = self.queryset.values('region').distinct()
            region_choices = [(k, v) for k, v in REGION_CHOICES if k in regions]
            self.filters['region'].choices = region_choices
    

    注意:我尚未对此进行测试,但希望足以为您指明正确的方向。

    【讨论】:

      【解决方案2】:

      夏尔巴人差点搞定:

      class AnimalFilter(FilterSet):
          def __init__(self, *args, **kwargs):
              #we are going to need the form underneath the filter, so init parent
              super().__init__(*args, **kwargs)
              #use a flat values list to get a queryset list good enough for this
              #can wrap in list() to force evaluation and get list of values only
              regions = self.queryset.values_list('region',flat=True).distinct()
              region_choices = [(k, v) for k, v in REGION_CHOICES if k in regions]
              #filter hands off to subclassed form for widgets, attach there
              self.form.fields['region'].choices = region_choices
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-02
        • 1970-01-01
        • 2018-09-29
        • 2017-03-28
        • 2019-07-29
        • 1970-01-01
        • 1970-01-01
        • 2014-10-25
        相关资源
        最近更新 更多