Why .filter() in django returns duplicated objects

2020-04-02 09:37发布

I've followed django tutorial and arrived at tutorial05.

I tried to not show empty poll as tutorial says, so I added filter condition like this:

class IndexView(generic.ListView):
    ...
    def get_queryset(self):
        return Question.objects.filter(
            pub_date__lte=timezone.now(),
            choice__isnull=False
        ).order_by('-pub_date')[:5]

But this returned two objects which are exactly same.

I think choice__isnull=False caused the problem, but not sure.

标签: django
2条回答
The star\"
2楼-- · 2020-04-02 09:57

choice__isnull causes the problem. It leads to join with choice table (to weed out questions without choices), that is something like this:

SELECT question.*
  FROM question
  JOIN choice
    ON question.id = choice.question_id
 WHERE question.pub_date < NOW()

You can inspect query attribute of QuerySet to be sure. So if you have one question with two choices, you will get that question two times. You need to use distinct() method in this case: queryset.distinct().

查看更多
▲ chillily
3楼-- · 2020-04-02 10:10

Because you created two objects with same properties. If you want to ensure uniqueness, you should add validation in clean and add unique index on identifier field too.

Besides filter returns all the objects that match the criteria, if you are expecting only one item to be returned, you should use get instead. get would raise exception if less or more than 1 item is found.

查看更多
登录 后发表回答