Django 注释返回重复条目

key*_*anm 4 django django-queryset django-annotate

我像这样注释一个查询集:

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)
            ),
        )
Run Code Online (Sandbox Code Playgroud)

在此示例中,SubItem是一个具有 外键的模型Item

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

带注释的查询集基本上如下所示:

[
    {
        'name': 'Item Name',
        'count_subitems': 1,
        'has_sent_subitem': False
    },
    {
        'name': 'Item Name',
        'count_subitems': 1,
        'has_sent_subitem': True
    }
]
Run Code Online (Sandbox Code Playgroud)

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

item = Item()
SubItem(item=item, status=draft)
SubItem(item=item, status=sent)
Run Code Online (Sandbox Code Playgroud)

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

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

bdb*_*dbd 7

您可以改为使用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)
            ),
        )
Run Code Online (Sandbox Code Playgroud)