反向反向外键上的Django Order By会丢弃没有关系的项目

问题描述 投票:0回答:1

上下文

我正在尝试根据反向外键关系的值对对象列表进行排序。我有部分解决方案,但是使用的过滤器创建了一个内部联接,该联接删除了没有关系的对象。

我想用所有对象创建排序的查询集的结果,威胁“空”反向关系,就好像相关值是空的。

型号

class Student(models.Model):
    name = models.CharField(max_length=128)


class Subject(models.Model):
    title = models.CharField(max_length=128)

class Grade(models.Model):
    student = models.ForeignKey("Student", related_name="grades", on_delete=models.CASCADE)
    subject = models.ForeignKey("Subject", related_name="grades", on_delete=models.CASCADE)
    value = models.IntegerField()

固定装置

+------+------------------------+
| name | subject  | grade_value |
+------+----------+-------------+
| beth | math     | 100         |
| beth | history  | 100         |
| mark | math     | 90          |
| mark | history  | 90          |
| mike | history  | 80          |
+------+----------+-------------+

期望的结果

[按学生的[[“历史”]]年级对他们进行排序时,我想获得[ beth (100), mark (90), mike (80) ]现在让我们说mark在家生病,错过了math考试。

按学生的[[“ math”

等级对其排序时,我想获得[ beth (100), mark (90), mike (null) ]

相反,对于按数学等级排序的结果,返回[ beth (100), mark (90) ]

尝试的解决方案

我知道我可以全部获取并重新加入结果,但是如果可能,我正在寻找一种有效的ORM查询集解决方案。

>>> Student.objects.filter(grades__subject__title="history").order_by("grades__value") <Student: Beth>, <Student: Mark>, <Student: Mike> >>> Student.objects.filter(grades__subject__title="math").order_by("grades__value") <Student: Beth>, <Student: Mark>

更新

我尝试按照建议使用联合,但是我不确定为什么会导致相关查找失败:

>>> Student.objects.filter(grades__subject__title="math")\ .union(Student.objects.all())\ .order_by("grades__value") ... django.core.exceptions.FieldError: Cannot resolve keyword 'value' into field. Choices are: grades, id, name

解决方案

下面使用@schillingt的解决方案进行的验证。

grades = Grade.objects.filter( student_id=OuterRef('id'), subject__title="math" ) students = Student.objects.annotate( subject_grade=Subquery(grades.values('value')[:1]) )

>>> [f"{s.name}: {s.subject_grade}" for s in students.order_by("subject_grade")] ['mike: None', 'mark: 90', 'beth: 100'] >>> >>> [f"{s.name}: {s.subject_grade}" for s in students.order_by("-subject_grade")] ['beth: 100', 'mark: 90', 'mike: None'] >>>

上下文,我正在尝试根据反向外键关系的值对对象列表进行排序。我有部分解决方案,但是使用的过滤器创建了一个内部联接,该联接删除了没有......>
python django django-models django-orm
1个回答
1
投票
from django.db.models import Subquery, OuterRef subject = "math" grades = Grade.objects.filter( student_id=OuterRef('id'), subject__title=subject, ).order_by('value') students = Student.objects.annotate( annotated_grade=Subquery(grades.values('value')[:1]), ) print(students.first().annotated_grade) # The first student's highest math grade.
© www.soinside.com 2019 - 2024. All rights reserved.