在Django筛选器和Wagtail中使用ModelChoiceFilter时如何防止重复

时间:2019-04-24 14:20:49

标签: django-models wagtail django-filter django-filters

我正在尝试对Wagtail Page模型和Orderable模型使用过滤器。但是我现在在过滤器中得到了重复项。我该如何解决这样的问题?

我的代码:

class FieldPosition(Orderable):
    page                        = ParentalKey('PlayerDetailPage', on_delete=models.CASCADE, related_name='field_position_relationship')
    field_position              = models.CharField(max_length=3, choices=FIELD_POSITION_CHOICES, null=True)

    panels = [
        FieldPanel('field_position')
    ]

    def __str__(self):
        return self.get_field_position_display()



class PlayerDetailPage(Page):
    content_panels              = Page.content_panels + [
                                                        InlinePanel('field_position_relationship', label="Field position", max_num=3),
    ]


class PlayerDetailPageFilter(FilterSet):
    field_position_relationship          = filters.ModelChoiceFilter(queryset=FieldPosition.objects.all())

    class Meta:
        model = PlayerDetailPage
        fields = []

所以我想做的是创建一个过滤器,该过滤器使用FIELD_POSITION_CHOICES中的条目过滤掉在Wa中的嵌入式面板中声明了具有此位置的任何页面。

如下面的图片所示,过滤器通过并且页面正在呈现。 (这些是2页,列出3个字段的位置)。

enter image description here

因此,第1页和第2页都具有“ Left Winger”条目,因此这是下拉菜单中的两倍。过滤效果很好。

我该怎么做才能防止这种情况?

解决方案应该是这样的(为此向哈里斯致谢):

基本上,每个页面字段位置都有一个FieldPosition对象,因此它正确列出了所有对象。我怀疑我不应该在那儿使用模型选择器,而是在FIELD_POSITION_CHOICES中使用硬编码值的列表,然后再使用过滤器来执行看起来像PlayerDetailPage.objects.filter(field_position_relationship__field_position=str_field_position_choice)的查询。但是,Django Filter的实现方式是什么?

2 个答案:

答案 0 :(得分:0)

拉夫

在我有限的简单视图中,它看起来像

class PlayerDetailPageFilter(FilterSet):
    field_position_relationship = filters.ModelChoiceFilter(queryset=FieldPosition.objects.all())

将返回FieldPosition的所有对象,如果此处有2个“左翼”条目(一个用于第1页,一个用于第2页),则可以认为这在您的列表中是重复的。那么,您是否尝试过使用.distinct过滤此列表查询集?也许像

class PlayerDetailPageFilter(FilterSet):
    field_position_relationship = filters.ModelChoiceFilter(queryset=FieldPosition.objects.values('field_position').distinct())

答案 1 :(得分:0)

经过反复试验,我找到了解决方案:

过滤器:

class PlayerDetailPageFilter(FilterSet):
    field_position_relationship__field_position     = filters.ChoiceFilter(choices=FIELD_POSITION_CHOICES)

    class Meta:
        model = PlayerDetailPage
        fields = []

然后是这样的视图:

context['filter_page'] = PlayerDetailPageFilter(request.GET, queryset=PlayerDetailPage.objects.all()

通过使用与field_position相关的ParentalKey field_position_relationship的相关名称访问__

然后使用Django过滤器ChoiceFilter,现在从选择列表中获取所有硬编码的条目,并将它们与PlayerDetailPage查询集中的条目进行比较。

在模板中,我可以使用Django Filter方法获取列表,然后循环遍历查询集:

<form action="" method="get">

{{ filter_page.form.as_p }}

<input type="submit" />
</form>

{% for obj in filter_page.qs %}
{{ obj }} >
{% endfor %}