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.
您可以改为使用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)
| 归档时间: |
|
| 查看次数: |
1914 次 |
| 最近记录: |