Django:通过几个多值关系来表达

时间:2016-03-04 06:33:22

标签: python django postgresql django-queryset django-orm

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):

Expected output

但相反,我会根据每个contests Entries的数量获得重复元素(通知竞赛4和5):

Actual output

此时,我尝试将Contest添加到查询集的末尾,但由于考虑了新的distinct()注释,我仍然会获得{{1}的重复项}。

Output with distinct()

由于我在Django> = 1.8并使用Postgres,我想到了使用complete。遗憾的是,这在Contest 4中设置为distinct("id")

Output with distinct("id")

这就是我决定发布这个问题的部分。关于如何从当前结果到预期结果(第一个表)的任何指针?我是否通过使用条件注释来忽略某些事情?

1 个答案:

答案 0 :(得分:3)

您可以添加order_bydistinct来获得所需的结果。

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的第一行,并删除其他行。