在 Django Filter 和 Wagtail 中使用 ModelChoiceFilter 时如何防止重复

How to prevent duplicates when using ModelChoiceFilter in Django Filter and Wagtail

我正在尝试将过滤器与 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 中的条目来过滤掉任何在 Wagtail 的内联面板中声明了此位置的页面。

正如您在下图中所见,过滤器正在通过并且正在呈现页面。 (这些是包含 3 个字段位置列表的 2 页)。

所以第 1 页和第 2 页都有一个 "Left Winger" 条目,所以这是下拉列表中的双条目。过滤效果很好。

我能做些什么来防止这种情况发生?

解决方案应该是这样的(感谢 Harris):

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

拉夫

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

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

将 return 来自 FieldPosition 的所有对象,如果您在此处有 2 个 'left wing' 条目(一个用于第 1 页,一个用于第 2 页),那么这将是有意义的在您的列表中重复。那么您是否尝试过使用 .distinct 过滤此列表查询集?也许像

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

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

过滤器:

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()

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

然后使用 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 %}