Django使用prefetch_related无法正常工作以避免额外查询

时间:2015-11-05 17:36:52

标签: django

我之前曾在select_relatedprefetch_related工作,效果很好。

我正在处理当前项目,由于某种原因,我无法弄清楚为什么我的预取相关查询无法正常工作,因此我得到了大量冗余的数据库调用。

我的模特:

class User(models.Model):
    user_extra_info = models.ManyToManyField(
        AppGeneralData,
        through='UserExtraInfo',
        null=True,
        blank=True
    )

class AppGeneralData(models.Model):
    title = models.CharField(max_length=255)
    type = models.PositiveSmallIntegerField(
        choices=GENERAL_DATA_TYPE
    )

class UserExtraInfo(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    info_item = models.ForeignKey(AppGeneralData)

QuerySet:

User.objects.all().prefetch_related(
    Prefetch(
        'userextrainfo_set',
        queryset=UserExtraInfo.objects.select_related('info_item').all()
    )
)

问题

当迭代查询集并调用子查询时,它不会从缓存的查询集中获取它:

for user in qs:
    user.userextrainfo_set.filter(
        info_item__type=general_data_type
    ).values_list(
        'info_item__title', flat=True
    ))

子查询只是在每次通话时转到数据库,我不明白我错过了什么。

感谢。

1 个答案:

答案 0 :(得分:5)

当您致电filter()时,会创建一个不同的查询集,因此Django无法使用prefetch_related中的数据。

您可以将过滤器移动到Prefetch对象的查询集中。

qs = User.objects.all().prefetch_related(
    Prefetch('userextrainfo_set', queryset=UserExtraInfo.objects.filter(
        info_item__type=general_data_type
    ).select_related('info_item'), to_attr='general_userextrainfo')
)

然后在访问查询集中的相关项时不要使用filter()

for user in qs:
    user.general_userextrainfo.values_list('info_item__title', flat=True))