在Django中计算聚合相关模型时出错

时间:2017-08-21 14:10:31

标签: django

我有以下型号:

class Contest(models.Model):
    id_contest = models.AutoField(primary_key=True)
    name = models.CharField(max_length=50, blank=False)

class Registration(models.Model):
    id_registration = models.AutoField(primary_key=True)
    team = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.DO_NOTHING,
        related_name='registrations',
        related_query_name='registration')
    contest = models.ForeignKey(
        Contest,
        on_delete=models.DO_NOTHING,
        related_name='registrations',
        related_query_name='registration')
    created_at = models.DateTimeField(null=True)
    confirmed_at = models.DateTimeField(null=True)

class Submission(models.Model):
    id_submission = models.AutoField(primary_key=True)
    team = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.DO_NOTHING,
        related_name='submissions',
        related_query_name='submission')
    contest = models.ForeignKey(
        Contest,
        on_delete=models.DO_NOTHING,
        related_name='submissions',
        related_query_name='submission')
    submitted_at = models.DateTimeField(null=True)
    is_valid = models.NullBooleanField()
    public_score = models.FloatField(null=True)

我正在处理排行榜查询(PostgreSQL),如:

select 
    r.team_id,
    max(t.username) as team_name,
    count(s.team_id) as num_submissions,
    min(s.public_score) as score,
    max(s.submitted_at) as last_submission,
    max(r.confirmed_at) as confirmation
from api_registration r
left join auth_user t on (r.team_id = t.id)
left join api_submission s on (r.contest_id = s.contest_id and s.team_id = t.id and s.is_valid = TRUE)
where r.contest_id = 1
group by r.team_id
order by score ASC, last_submission DESC;

返回我想要的结果。 但是,在转换为Django QuerySet操作时,最接近的是我 来的是:

leaderboard = Registration.objects \
              .filter(contest=contest, contest__submission__is_valid=True) \
              .annotate(team_name=Max('team__username'),
                        num_submissions=Count('team__submission'),
                        score=Min('contest__submission__public_score'),
                        last_submission=Max('contest__submission__submitted_at'),
                        confirmation=Max('confirmed_at')) \
              .order_by('score', '-last_submission')

生成查询:

SELECT
"api_registration"."id_registration",
"api_registration"."team_id",
"api_registration"."contest_id",
"api_registration"."created_at",
"api_registration"."confirmed_at",
MAX("api_registration"."confirmed_at") AS "confirmation",
MAX("api_submission"."submitted_at") AS "last_submission",
MAX("auth_user"."username") AS "team_name",
MAX("api_submission"."public_score") AS "score",
COUNT(T5."id_submission") AS "num_submissions"
FROM "api_registration" INNER JOIN "api_contest" ON ("api_registration"."contest_id" = "api_contest"."id_contest")
INNER JOIN "api_submission" ON ("api_contest"."id_contest" = "api_submission"."contest_id")
INNER JOIN "auth_user" ON ("api_registration"."team_id" = "auth_user"."id")
LEFT OUTER JOIN "api_submission" T5 ON ("auth_user"."id" = T5."team_id")
WHERE ("api_registration"."contest_id" = 1
AND "api_submission"."is_valid" = True)
GROUP BY "api_registration"."id_registration"
ORDER BY "score" ASC, "last_submission" DESC;

并且没有正确计算每个团队提交的正确数量。 有关如何定义Django QuerySet操作以获得正确结果的任何帮助吗?

1 个答案:

答案 0 :(得分:0)

尝试更改此内容:num_submissions=Count('team__submission'), num_submissions=Count('team_id'),

这是根据表注册的team_id进行分组。