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

做~自己de王妃 提交于 2019-12-13 03:36:10

问题


I am trying to use filters with a Wagtail Page model and a Orderable model. But I get duplicates in my filter now. How can I solve something like this?

My code:

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 = []

So what I am trying to do is create a filter which uses the entries from FIELD_POSITION_CHOICES to filter out any page that has this position declared in the inline panel in Wagtail.

As you can see in the picture down below, the filters are coming through and the page is being rendered. (These are 2 pages with a list of 3 field positions).

So Page 1 and Page 2 both have a "Left Winger" entry, so this is double in the dropdown. The filtering works perfectly fine.

What can I do to prevent this?

The solution should be something like this (Credits to Harris for this):

I basically have one FieldPosition object per page-field position, so it's listing all of the objects correctly. I suspect I should not use the model chooser there, but a list of the hard coded values in FIELD_POSITION_CHOICES and then a filter to execute a query that looks something like PlayerDetailPage.objects.filter(field_position_relationship__field_position=str_field_position_choice). But what is the Django Filter way of doing this?


回答1:


Raf

In my limited simplistic view it looks like

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

is going to return all the objects from FieldPosition and if you have 2 entries for 'left wing' in here (one for page 1 and one for page 2) then it would make sense that this is duplicating in your list. So have you tried to filter this list queryset with a .distinct? Perhaps something like

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



回答2:


I found the solution after some trial and error:

The filter:

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

    class Meta:
        model = PlayerDetailPage
        fields = []

And then the view just like this:

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

By accessing the field_position through the related name of the ParentalKey field_position_relationship with __.

Then using the Django Filter ChoiceFilter I get all the hard-coded entries now from the choice list and compare them against the entries inside the PlayerDetailPage query set.

In the template I can get the list using the Django Filter method and then just looping through the query set:

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

{{ filter_page.form.as_p }}

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

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


来源:https://stackoverflow.com/questions/55832348/how-to-prevent-duplicates-when-using-modelchoicefilter-in-django-filter-and-wagt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!