最新的外键的Django Queryset

时间:2018-01-26 19:13:13

标签: django django-views django-queryset

我有3个链接的Django模型。

models.py

Assessment(models.Model):
    finalized = models.BooleanField(default=False)
    finalized_date = models.DateTimeField(default=blank, blank=True)
    workstation = models.ForeignKey(Assessment, null=True, blank=True, on_delete=models.SET_NULL)
    class Meta:
         get_latest_by = "finalized_date"

Workstation(models.Model):
    pass

Answer(models.Model):
    score = models.IntegerField(default=0)
    assessment = models.ForeignKey(Assessment, null=True, blank=True, on_delete=models.SET_NULL)

这是我的第一个问题:

我需要一个返回所有最新评估(L)的查询集。

例如,(L)是最新的:

Workstation 1    |   Workstation 2    | Workstation 3
------------------------------------------------------
Assessment 1 (L) |  Assessment 12     | Assessment 4
Assessment 2     |  Assessment 41     | Assessment 15 (L)
Assessment 3     |  Assessment 99 (L) | Assessment 9

因此查询集应返回:Assessment 1, Assessment 99 and Assessment 15

我考虑过做一个工作站的查询集,然后进行for循环,但这样做成本太高,并产生了大量的查询。

第二个问题(与第一个问题相关):

我实际上需要一个与工作站最新评估相关的所有Answers的查询集。

我认为我可以将其分解为多个查询集以使其正常工作,但如果有办法从一个查询集中执行此操作,请教育我!

所以,一旦我从#1获得了Assessments的查询集,我就会使用follow querysets来获取我真正需要的内容。

final_queryset = Answer.objects.filter(assessment__in=QuerySet_From_Problem_1)

1 个答案:

答案 0 :(得分:1)

第一个问题

首先,我认为你的Assessment -- Workstation关系是倒置的。根据您的要求,Workstation可以有多个Assessments,因此模型应为:

Assessment(models.Model):
    workstation = models.ForeignKey(Assessment, null=True, 
                                    blank=True, on_delete=models.SET_NULL)
    finalized = models.BooleanField(default=False)
    finalized_date = models.DateTimeField(default=blank, blank=True)

    class Meta:
         get_latest_by = "finalized_date"

Workstation(models.Model):
    pass

现在,为了得到你想要的东西,你可以使用Django 1.11中引入的Subquery feature

from django.db.models import OuterRef, Subquery
latest = Assessment.objects.filter(
    workstation=OuterRef('pk')).order_by('-finalized_date')

workstations = Workstation.objects.annotate(
    latest_assessment_id=Subquery(latest.values('pk')[:1]))
for workstation in workstations:
    print('Assessment {}'.format(workstation.latest_assessment_id))

第二个问题

现在您已经拥有评估ID,正如您所说,您只需得到答案:

latest_assessments_ids = (w.latest_assessment_id for w in workstations)
answers = Answer.objects.filter(assessment_id__in=latest_assessments_ids)