【问题标题】:Django Queryset with Latest of Foreignkey带有最新外键的 Django 查询集
【发布时间】:2018-07-06 04:31:33
【问题描述】:

我有 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 循环,但这样做成本太高并且会产生大量查询。

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

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

我认为我可以将其分解为几个查询集以使其工作,但如果有一种方法可以从一个查询集中做到这一点,请教育我!

因此,一旦我获得了来自 #1 的评估查询集,我将只使用以下查询集来获得我真正需要的内容。

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

【问题讨论】:

    标签: django django-views django-queryset


    【解决方案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)
    

    【讨论】:

    • 你是最棒的。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2011-10-29
    • 2015-03-09
    • 2015-01-05
    • 2019-07-14
    • 2019-08-17
    • 2015-01-25
    • 2013-02-27
    • 2013-09-27
    相关资源
    最近更新 更多