我之前曾在select_related
和prefetch_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
))
子查询只是在每次通话时转到数据库,我不明白我错过了什么。
感谢。
答案 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))