Django 1.8和1.9,Postgres DB。
我有一个div
模型,可以有Contest
提交的许多相关Entry
个对象。
Users
我希望获得所有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)
个对象的列表,并使用Contest
标记进行注释,以指示特定complete
是否为每个user
提交了Entry
}。
Contest
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(),
)
)
上的预期结果将是这样的(对于user1):
但相反,我会根据每个contests
Entries
的数量获得重复元素(通知竞赛4和5):
此时,我尝试将Contest
添加到查询集的末尾,但由于考虑了新的distinct()
注释,我仍然会获得{{1}的重复项}。
由于我在Django> = 1.8并使用Postgres,我想到了使用complete
。遗憾的是,这在Contest 4
中设置为distinct("id")
。
这就是我决定发布这个问题的部分。关于如何从当前结果到预期结果(第一个表)的任何指针?我是否通过使用条件注释来忽略某些事情?
答案 0 :(得分:3)
您可以添加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
的行< / em>的)。然后,使用distinct('id')
保留每个id
的第一行,并删除其他行。