如何在select_related模型上添加注释?

时间:2019-05-04 17:08:01

标签: django orm

我为我的查询集中的每个对象选择了一个相关对象。如何为每个注释一个计算值?

型号:

class School(models.Model):
    name = models.CharField(max_length=255)


class Teacher(models.Model):
    name = models.CharField(max_length=255)
    school = models.ForeignKey(School)


class Student(Entity):
    name = models.CharField(max_length=255)
    school = models.ForeignKey(School)

我想获取所有老师,以及每个学校的学生以及该学校的学生人数。

这是我尝试过的:

teachers = Teacher.objects.select_related('school').annotate(student_count=Count('school__student'))

但是我可以看到这是错误的,因为每个学校的学生人数必须是

我希望以后可以对我的查询集执行以下操作:

for teacher in teachers:
  print(teacher.name, teacher.school.name, teacher.school.student_count)

1 个答案:

答案 0 :(得分:0)

  

但是我可以看到这是错误的,因为每个学校的学生人数必须是

那么您将计算该老师所属学校的学生,所以这在语义上是有效的。但是,注释将被放置在查询集中的对象上,从而被放置在教师身上,因此您可以通过以下方式获取学生人数:

onPause

由于多个老师可以属于同一所学校,因此以这种方式进行注释可能是最好的主意,因为如果未进行优化,则意味着您将计算该所学校的学生人数每个老师。尽管从语义上讲不会改变任何内容,但查询可能会花费大量时间。

您可以决定为给定的for teacher in teachers: print(teacher.name, teacher.school.name, teacher.student_count)使用.prefetch_related(..),并在Prefetch object [Django-doc]中注释该查询集,这将导致额外的查询,但会降低查询的成本。例如:

school

那么您确实可以使用以下方法进行查询:

from django.db.models import Prefetch, Count

teachers = Teacher.objects.prefetch_related(
    Prefetch(
        'school',
        queryset=School.objects.annotate(student_count=Count('student'))
    )
)