prefetch_related 上的 Django ORM 注释

Posted

技术标签:

【中文标题】prefetch_related 上的 Django ORM 注释【英文标题】:Django ORM annotation on prefetch_related 【发布时间】:2017-04-24 20:05:29 【问题描述】:

如何在 prefetch_related 查询期间注释相关模型?

我有两个模型:

class Subject(models.Model):
    ...

class Student(models.Model):
    subjects = models.ManyToManyField(Subject, related_name="students")

我想在单个查询中检索 Subject 对象,与每个 Subject 相关的 Student 对象以及每个 Student 具有的数量。 我正在尝试使用以下查询来完成它:

Subject.objects.all().prefetch_related( Prefetch("student", queryset=Student.objects.all().annotate(subjects_count=Count("subject"))) )

但是我得到一个 SQL 错误:

OperationalError at /concerts/coldplay-en-madrid/ (1055, "Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'studentsubject.subject_id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by")

【问题讨论】:

尝试这样做:Subject.objects.annotate(subjects_count=Count('students')).prefetch_related('students') 这样我得到了每个科目有多少学生,但我想得到相反的关系:每个学生有多少科目。无论如何感谢您的帮助! 【参考方案1】:

因此,根据您的要求,您可以制作一个“通过”表来处理主题和学生之间的 M2M 关系。所以,你的模型看起来像:

class Subject(models.Model):
    # ...

class Student(models.Model):
    subjects = models.ManyToManyField(
                   to=Subject,
                   through='StudentSubject',
                   related_name="students")

class StudentSubject(models.Model):
    student = models.ForeignKey(to=Student, related_name='student_subjects')
    subject = models.ForeignKey(to=Subject, related_name='subject_students')

您可以通过here 的表格了解更多信息。 现在,您可以这样查询:

from django.db.models import Count
students = Student.objects.prefetch_related('student_subjects')

subjects_associated_with_students = (
    students.annotate(num_subjects=Count('student_subjects'))

subjects_associated_with_students 是一个查询集,您现在可以使用它执行任何常规操作。对于前-subjects_associated_with_students.filter(num_subjects__gt=1)。这将为您提供至少拥有 1 个科目的所有学生。

希望对你有帮助。

【讨论】:

我认为这不是正确的答案。我想获得Subject 对象,但使用此解决方案我将获得Students。谢谢!

以上是关于prefetch_related 上的 Django ORM 注释的主要内容,如果未能解决你的问题,请参考以下文章

django- 在另一个 prefetch_related 中使用 prefetch_related

AttributeError:“Resume”对象没有“prefetch_related”属性

Django:prefetch_related 没有效果

Django:prefetch_related() 是不是遵循反向关系查找?

prefetch_related 多个级别

关于函数'prefetch_related'的'* lookups'参数的变种