我使用优秀的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)
[...]
现在,如果我在模板中渲染过滤器,我仍然可以获得区域的两个选项 Europe 和 Africa ,尽管查询集只包含一个具有区域非洲。 任何想法如何为模板中呈现的区域字段获取正确的选项?非常感谢任何帮助。
答案 0 :(得分:0)
您可以覆盖choices
中的FilterSet.__init__()
,以确保区域选择仅限于基于提供的查询集的区域。
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
注意:我还没有对此进行测试,但希望足以让您指出正确的方向。
答案 1 :(得分:0)
夏尔巴人几乎拥有它:
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