我有一个Review
模型,并且有一个ReviewScore
ForeignKey,表示某个时间点的分数。简化,它看起来像这样:
class Review(models.Model):
# Nothing interesting here.
class ReviewScore(models.Model):
review = models.ForeignKey(Review)
date = models.DateField()
score = models.IntegerField()
class Meta:
ordering = ("-date",)
在我看来,我希望使用ReviewScore表中最新一行的score
值注释一个Review查询集(具体来说,我不想要平均值),这样我就可以根据评论的最新分数进行排序。
我已经尝试了.annotate(score=F("reviewscore__score"))
,但这会返回多行;因此它返回重复Review
个,每个都使用不同的ReviewScore分数进行注释,并且使用distinct
无法解决此问题,因为Postgres要求distinct
必须与ORDER BY表达式匹配。
这可能吗?我可以以某种方式过滤或限制使用.annotate
返回外表的结果,或者只使用ReviewScore
表中的第一个结果进行注释吗?
答案 0 :(得分:1)
以下内容应使用您所指的Postgres功能(distinct(*fields)
):
Review.objects
.annotate(score=F("reviewscore__score"), date=F("reviewscore__date"))
.order_by('pk', '-date') # groups by id and descending date
.distinct('pk')
如果你想要一个不同于pk
的显示顺序,我认为你必须在Python中排序,因为任何带有pk__in
的嵌套过滤器都会丢失注释。
答案 1 :(得分:1)
在最新的Django版本中,您可以在注释中使用Subquery expressions:
from django.db.models import OuterRef, Subquery
scores = ReviewScore.objects.filter(review=OuterRef("pk")).order_by("-date")
reviews = Review.objects.annotate(
latest_score=Subquery(scores.values("score")[:1])
)
sorted_reviews = reviews.order_by('latest_score')
这样,您可以与数据库无关(例如,与sqlite3一起使用)。