【问题标题】:Django annotate returning duplicate entriesDjango注释返回重复条目
【发布时间】:2021-12-26 08:50:23
【问题描述】:

我正在像这样注释查询集:

class ItemQuerySet(models.QuerySet):
    def annotate_subitem_stats(self):
        return self.annotate(
            count_subitems=Count('subitems'),
            has_sent_subitems=Case(
                When(subitems__status=Status.sent, then=Value(True)),
                default=Value(False)
            ),
        )

在本例中,SubItem 是一个模型,其外键指向 Item。

当我运行此代码时发生了一个奇怪的行为。假设我们有 1 个Item 和 2 个SubItems 链接到它。一个子项已发送状态,而另一个则没有。当我在查询集上运行注释时,查询集返回该项目两次,一次将has_sent_subitems 设置为True,另一次设置为False。另一个奇怪的是,一个重复有count_subitems == 1,另一个有count_subitems == 1,好像查询集已经将项目分成两行,一个在status == 'sent',另一个在status != 'sent'。

这基本上就是带注释的查询集的样子:

[
    {
        'name': 'Item Name',
        'count_subitems': 1,
        'has_sent_subitem': False
    },
    {
        'name': 'Item Name',
        'count_subitems': 1,
        'has_sent_subitem': True
    }
]

这是数据库的样子,使用伪代码:

item = Item()
SubItem(item=item, status=draft)
SubItem(item=item, status=sent)

我很确定这与When(subitems__status=Status.sent, then=Value(True)), 行有关。有什么办法可以让那行检查是否只有 1 个项目已发送状态,然后将注释设置为 true 并继续?

附:使用 .distinct() 不起作用。我不能使用.distinct(field),因为annotate() + distinct(fields) is not implemented.

【问题讨论】:

    标签: django django-queryset django-annotate


    【解决方案1】:

    您可以改为使用Exists 子查询,以避免subitems__status 引起的连接,所以:

    from django.db.models import Exists, OuterRef
    
    
    class ItemQuerySet(models.QuerySet):
        def annotate_subitem_stats(self):
            return self.annotate(
                count_subitems=Count('subitems'),
                has_sent_subitems=Exists(
                    SubItem.objects.filter(item=OuterRef('pk'), status=Status.sent)
                ),
            )
    

    【讨论】:

    • 我想知道,由于SubItem.objects.filter 调用,这是否会触发查询集中每个项目的查询?
    • 不应该,因为子查询仍然是“主”查询的一部分
    猜你喜欢
    • 2016-02-02
    • 2016-09-09
    • 1970-01-01
    • 1970-01-01
    • 2012-10-26
    • 1970-01-01
    • 2012-07-02
    • 2011-10-23
    • 2015-10-21
    相关资源
    最近更新 更多