Django 1.8和1.9,邮政数据库。
我有一个Contest
模型,它可以有许多由Entry
提交的相关对象。
class Contest(models.Model):
title = models.CharField(max_length=50)
class Entry(models.Model):
contest = models.ForeignKey(Contest, related_name="entries")
user = models.ForeignKey(settings.AUTH_USER_MODEL)
我想得到一个所有
Users
对象的列表,用Contest
标记进行注释,指示特定complete
是否为每个user
提交了Entry
。from django.db.models import Case, When, BooleanField, Value
user = User.objects.get(...)
contests = Contest.objects.annotate(
complete=Case(
When(entries__user=user, then=Value(True)),
default=Value(False),
output_field=BooleanField(),
)
)
Contest
上的预期结果如下(对于user1):但是,我得到的是重复的元素,这取决于每个
contests
上Entries
的数量(请注意竞赛4和竞赛5):在这一点上,我尝试将
Contest
添加到queryset的末尾,但是由于考虑了新的distinct()
注释,我仍然得到了complete
的副本。因为我在Django>=1.8上使用Postgres,所以我想使用
Contest 4
。不幸的是,在distinct("id")
中设置为False
。这就是我决定提出这个问题的部分。关于如何从当前结果到预期结果(第一个表)的指针?我是否通过使用条件注释而忽略了某些内容?
最佳答案
您可以同时添加order_by
和distinct
以获得所需的结果。
contests = Contest.objects.annotate(
complete=Case(
When(entries__user=user, then=Value(True)),
default=Value(False),
output_field=BooleanField(),
)
).order_by('id', '-complete').distinct('id')
请注意
distinct
文档中的以下注释指定字段名时,必须在QuerySet中提供
order_by()
,order_by()
中的字段必须以相同顺序以distinct()
中的字段开头。例如,
SELECT DISTINCT ON (a)
为column a
中的每个值提供第一行。如果不指定顺序,将得到任意行。因此,首先按
id
对结果进行排序,然后按complete
的降序排序(否则将得到顶部有complete=False
的行)。然后,使用distinct('id')
保留每个id
的第一行并删除其他行。关于python - Django:通过多个多值关系进行注释,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35789487/