Django 注释返回重复条目
Django annotate returning duplicate entries
我正在像这样注释查询集:
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 SubItem
链接到它。一个子项的状态已发送,而另一个没有。当我 运行 在查询集上注释时,查询集 returns 项目两次,一次 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 并继续?
P.S。使用 .distinct()
无效。我不能使用 .distinct(field)
,因为 annotate() + distinct(fields) is not implemented.
您可以为此使用 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)
),
)
我正在像这样注释查询集:
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 SubItem
链接到它。一个子项的状态已发送,而另一个没有。当我 运行 在查询集上注释时,查询集 returns 项目两次,一次 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 并继续?
P.S。使用 .distinct()
无效。我不能使用 .distinct(field)
,因为 annotate() + distinct(fields) is not implemented.
您可以为此使用 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)
),
)