【发布时间】:2020-05-13 15:51:43
【问题描述】:
我目前在 Post 模型上拥有以下属性:
@property
def compliments(self):
compliments_by_kind = list(
self.compliment_set.values(
'kind'
).annotate(
amount=Count('kind')
).values(
'kind',
'amount'
)
)
for compliment_by_kind in compliments_by_kind:
compliment_by_kind['last_giver'] = self.compliment_set.filter(
kind=compliment_by_kind['kind']
).order_by(
'created'
).last().giver.name
return compliments_by_kind
这将返回以下列表数据结构:
[
{
'kind': 'unique',
'amount': 3,
'last_giver': 'Person 1'
},
{
'kind': 'fresh',
'amount': 2,
'last_giver': 'Person 2'
},
{
'kind': 'concept',
'amount': 3,
'last_giver': 'Person 3'
},
{
'kind': 'lines',
'amount': 1,
'last_giver': 'Person 4'
}
]
数据本身没有问题。在循环中执行查询的性能没有任何问题。
但是,循环方法 - 效率不高 - 对于每种类型(总共有 6 个,在一个之上还有 6 个进一步的查询来获得 Count 注释。所以,这确实妨碍了性能serialization舞台。
有没有人知道如何根据“种类”的“created”属性的排序来执行最新的Compliment“giver.name”的annotation......即最后一个人赞美“善良”独特等
这是Compliment 模型:
class Compliment(TimeStampedModel):
giver = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True,
related_name="giver",
)
receiver = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True,
related_name="receiver",
)
post = models.ForeignKey('blog.post', on_delete=models.CASCADE)
kind = models.CharField(choices=COMPLIMENTS_CHOICES, max_length=15)
更新:利用威廉的绝妙建议,我的解决方案是:
@property
def compliments(self):
from django.contrib.auth import get_user_model
from django.db.models import OuterRef, Subquery
compliments_by_kind = list(
self.compliment_set.values(
'kind'
).annotate(
amount=Count('kind'),
first_name=Subquery(
get_user_model().objects.filter(
giver__artwork_id=self.pk,
giver__kind=OuterRef('kind')
).values('first_name').order_by('-giver__created')[:1]
),
last_name=Subquery(
get_user_model().objects.filter(
giver__artwork_id=self.pk,
giver__kind=OuterRef('kind')
).values('last_name').order_by('-giver__created')[:1]
),
)
)
return compliments_by_kind
【问题讨论】:
-
您能否展示相关型号(
Compliments,以及与.giver相关的型号? -
@WillemVanOnsem 完全没有问题 - 已添加。
giver与标准 DjangoUser模型相关。kind纯粹是一个 Char 字符串,假设有任意数量的CHOICES。
标签: python django django-orm