我目前在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
注释。因此,这确实会影响[ C0]阶段。
[谁会知道如何根据“种类”的“ serialization
”属性的顺序,对最新的annotation
“ Compliment
”执行giver.name
...,即最后给出的人称赞“独特”等
这里是created
模型:
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
在同一查询中获得last_giver
(从而避免了[[N + 1问题