首页 > 解决方案 > 如何在 select_related 模型上进行注释?

问题描述

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

模型:

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)

标签: djangoorm

解决方案


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

好吧,您将计算属于该老师所属学校的学生,因此这在语义上是有效的。然而,注释将放在查询集中的对象上,因此是教师,因此您可以使用以下方法获取学生人数:

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

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

您可以决定对.prefetch_related(..)给定使用 a ,并在对象 [Django-doc]school中注释该查询集,这将导致额外的查询,但成本更低。例如:Prefetch

from django.db.models import Prefetch, Count

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

然后你确实可以查询:

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

推荐阅读