0

这是我经常遇到的问题。假设我有三个模型:

class CourseType(models.Model):
    name = models.CharField(max_length=50)

class CourseLevel(models.Model):
    name = models.CharField(max_length=50)
    course_type = models.ForeignKey(CourseType, on_delete=models.CASCADE)

class Course(models.Model):
    name = models.CharField(max_length=50)
    course_level = models.ForeignKey(CourseLevel, on_delete=models.CASCADE)

    def __str__(self):
        return "{}-{}: {}".format(self.course_level.course_type.name, self.course_level.name, self.name)

如果我要遍历Course.objects.all()并打印Course对象,那将是一个 n+1 查询。这很容易通过使用解决select_related

Course.objects.select_related('course_level', 'course_level__course_type')

问题是我必须记住select_related每次都使用。它也很丑陋,尤其是如果您在那里有另一个模型,例如CourseDetails.

一种解决方案是使用自定义管理器:

class CourseManager(models.Manager):
    def with_names(self):
        return self.select_related('course_level', 'course_level__course_type')

然后我可以使用Course.with_names.all(),不再需要select_related每次都添加。这有一个主要限制 - 我只能在直接使用Course. 很多时候我会通过外键迭代Course对象,并且我需要再次记住select_related在我的代码中使用和乱扔它。一个例子:

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

class StudentCourseEnroll(models.Model):
    student = models.ForeignKey(Student, on_delete=models.CASCADE)
    course = models.ForeignKey(Course, on_delete=models.CASCADE)

现在如果我想打印所有学生和他们注册的课程,我必须再次记住使用select_related它甚至更丑:

StudentCourseEnroll.objects.select_related('course__course_level__course_type', 'course__course_level')

我可以创建另一个经理,StudentCourseEnroll但这似乎违背了 DRY 原则——我会让多个经理做同样的事情。

有没有更好的方法来解决这个问题?我可以直接在Course模型中做些什么来避免考虑这个问题吗?

4

0 回答 0