【问题标题】:Why .filter() in django returns duplicated objects?为什么 .filter() 在 django 中返回重复的对象?
【发布时间】:2016-07-19 07:43:38
【问题描述】:

我已经按照 django 教程到达tutorial05

我试图不显示教程所说的空投票,所以我添加了这样的过滤条件:

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]

但这会返回两个完全相同的对象。

我认为 choice__isnull=False 导致了问题,但不确定。

【问题讨论】:

  • 您在数据库中有两个不同的对象具有相同的值
  • 检查对象 id 是否相同,然后返回重复记录,否则您会更清楚。
  • @Sayse 我查了表 polls_question,但没有重复的投票。
  • filter 不能两次返回同一个对象。您必须覆盖了您没有向我们展示的默认管理器(我对此表示怀疑),或者您有两个不同的对象。或者它在视图中的不正确逻辑
  • @Sayse 不正确,filter 能够两次返回同一个对象,见Django documentation for distinct

标签: django


【解决方案1】:

choice__isnull 导致问题。它导致加入choice 表(在没有choices 的情况下淘汰questions),是这样的:

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

您可以检查QuerySetquery 属性以确定。因此,如果您有一个question 和两个choices,您将获得两次question。在这种情况下,您需要使用distinct() 方法:queryset.distinct()

【讨论】:

  • 默认情况下,QuerySet 不会消除重复行。实际上,这很少会成为问题,因为像 Blog.objects.all() 这样的简单查询不会引入重复结果行的可能性。但是,如果您的查询跨越多个表,则在评估 QuerySet 时可能会得到重复的结果。那时你会使用 distinct()。
【解决方案2】:

只需在 ORM 末尾使用 .distinct()

【讨论】:

    【解决方案3】:

    聚会有点晚了,但我认为它可以帮助其他人查找相同的问题。 不要将choice__isnull=Falsefilter() 方法一起使用,而是将其与exclude() 一起使用,以排除任何没有选择的问题。所以你的代码看起来像这样:

        ...
        def get_queryset(self):
            return Question.objects.filter(pub_date__lte=timezone.now()).exclude(choice__isnull=True).order_by('-pub_date')[:5]
    

    通过这种方式,它将只返回question 的一个实例。不过请务必使用choice_isnull=True

    【讨论】:

      【解决方案4】:

      因为您创建了两个具有相同属性的对象。如果要确保唯一性,则应在clean 中添加验证,并在标识符字段上添加唯一索引。

      除了filter 返回所有符合条件的对象外,如果您希望只返回一项,则应使用get 代替。 get 会在发现少于或多于 1 个项目时引发异常。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-11
        • 2019-09-04
        • 2016-02-12
        • 2016-03-21
        • 1970-01-01
        • 2017-01-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多