自动注释通过多对多字段检索的 Django 模型

Dav*_*ver 6 django django-models

我有一个通过字段Student与模型相关的Course模型ManyToMany

class Student(Model):
    name = TextField()

class Course(Model):
    name = TextField()
    students = ManyToManyField(Student, through="StudentCourse")

class StudentCourse(Model):
    student = ForeignKey(Student)
    course = ForeignKey(Course)
    section_name = TextField()
Run Code Online (Sandbox Code Playgroud)

如何自动注释通过Course.students多对多字段检索到的学生及其课程中的部分?

例如,不必extra在每个查询上添加显式:

>>> students = course.students.extra(select={
...     "section_name": "app_student_course.section_name",
... })
>>> print students[0].section_name
u'First Section'
Run Code Online (Sandbox Code Playgroud)

我只能:

>>> students = course.students.all()
>>> print students[0].section_name
u'First Section'
Run Code Online (Sandbox Code Playgroud)

谢谢!

aja*_*est 5

是否可以按如下方式替换关系管理器。从那里你可以对查询集做任何你想做的事情:

from django.db.models.query import F

class Student(Model):
    name = TextField()

class Course(Model):
    name = TextField()
    students = ManyToManyField(Student, through="StudentCourse")

class StudentCourse(Model):
    # Set related_names so that it is easy to refer to the relation
    # with the through model
    student = ForeignKey(Student, related_name='student_courses')
    course = ForeignKey(Course, related_name='student_courses')
    section_name = TextField()

# Create a new customized manager
class StudentRelatedWithCourseManager(
    Course.students.related_manager_cls
):

    def get_queryset(self):
        # Gets the queryset of related Students ... 
        qs = super(StudentRelatedWithCourseManager, self)\
            .get_queryset()

        # Annotate it before is handled by the ManyRelatedDescriptor
        return qs.annotate(
            section_name=F('student_courses__section_name')
        )

# Replace the stock manager with your custom manager
Course.students.related_manager_cls = \
    StudentRelatedWithCourseManager
Run Code Online (Sandbox Code Playgroud)


Spe*_*udd 0

为什么不直接查询StudentCourse模型呢?例如:

StudentCourse.objects.filter(course=course)
Run Code Online (Sandbox Code Playgroud)

如果您要迭代StudentCourse对象并查询student属性,请使用select_related来确保您不会为每个学生执行额外的数据库查询。

student_courses = StudentCourse.objects.select_related('student').filter(course=course)
for sc in student_courses:
    print '%s: %s' % (sc.student.name, sc.section_name)
Run Code Online (Sandbox Code Playgroud)