我有以下型号

class Film(models.Model):
    crew = models.ManyToManyField('Person', through='Role', blank=True)

class Role(models.Model):
    person = models.ForeignKey('Person')
    film = models.ForeignKey('Film')
    person_role = models.ForeignKey(RoleType)
    credit = models.CharField(max_length=200)
    credited_as = models.CharField(max_length=100)

class RoleType(models.Model):
    """Actor, director, makeup artist..."""
    name = models.CharField(max_length=50)

class Person(models.Model):
    slug = models.SlugField(max_length=30, unique=True, null=True)
    full_name = models.CharField(max_length=255)

一个Film(“星球大战:克隆人 war ”)有几个Person(“克里斯托弗·李”),他们每个人可以有一个或多个Role(“杜库伯爵之声”),并每RoleRoleType(“声优”)。

我正在使用 DetailView 来显示 Film
class FilmDetail(DetailView):
    model = Film

在我的模板中,我显示了所有人员,因此每次我显示 Film 时都会执行 609 查询。为了减少这种情况,我想使用 prefetch_related 所以我将 View 更改为:
class FilmDetail(DetailView):
    model = Film

    def get_queryset(self):
        return super(FilmDetail, self).get_queryset().prefetch_related('crew')

但这并没有减少查询的数量(610),我尝试了以下参数来预取相关,但没有用:
def get_queryset(self):
        return super(FilmDetail, self).get_queryset().prefetch_related('crew__person_role')

我收到了 Cannot find 'person_role' on Person object, 'crew__person_role' is an invalid parameter to prefetch_related() 错误

我该怎么做才能从 Person.full_name 中预取 slugRole 以及所有 Film.crew 字段?

最佳答案

您可以像这样构造查询集:

from django.db.models import Prefetch

def get_queryset(self):
    return super(FilmDetail, self).get_queryset().prefetch_related(
        Prefetch(
            'crew',
            queryset=Role.objects.select_related(
                'person',
                'person_role',
            ),
        ),
    )

只有 Film->Role 是可加载 prefetch_related 的反向关系。 Role->RoleType 和 Role->Person 是您使用 select_related 加载的转发关系。

关于Django prefetch_related 与 m2m 通过关系,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35093204/

10-13 05:45