Django中prefetched_subtopics属性返回空值问题:如何正确在Campaign查询集中预取子主题
嘿,我看了你的代码,问题出在Prefetch的层级和to_attr的绑定位置上——你现在把prefetched_subtopics绑定到了中间关联表CampaignSubTopicAssn的实例上,但你想要的应该是让Campaign实例直接拥有这个属性对吧?
修正方案一:直接预取子主题到Campaign实例
把嵌套的Prefetch调整成直接跨关联路径预取,这样就能把子主题列表直接存到Campaign的prefetched_subtopics属性里:
def get_queryset(self): return super(CampaignViewSet, self).get_queryset().prefetch_related( Prefetch( 'subtopic_assn__subtopic', queryset=SubTopic.objects.all(), to_attr='prefetched_subtopics' ) )
修正方案二:保留中间表预取(如果需要用到关联表的额外字段)
如果你需要用到CampaignSubTopicAssn里的其他字段,可以先预取关联表,再预取子主题,同时把关联表的结果存到一个自定义属性里:
def get_queryset(self): return super(CampaignViewSet, self).get_queryset().prefetch_related( Prefetch( 'subtopic_assn', queryset=CampaignSubTopicAssn.objects.prefetch_related('subtopic'), to_attr='prefetched_subtopic_assns' ) )
之后你可以通过campaign.prefetched_subtopic_assns拿到所有关联表实例,再从中获取子主题:[assn.subtopic for assn in campaign.prefetched_subtopic_assns]
额外优化:给Campaign模型加属性包装
如果想更方便地获取子主题,可以给Campaign类加一个property,这样不用每次都手动遍历关联表:
class Campaign(Base): # 你的现有字段... @property def prefetched_subtopics(self): return [assn.subtopic for assn in self.subtopic_assn.all()]
只要你已经预取了subtopic_assn__subtopic,这个属性就会直接返回子主题列表,不会触发额外的数据库查询。
为什么原来的写法会返回空?
你之前的代码是在CampaignSubTopicAssn的预取操作里,把SubTopic存到了关联表实例的prefetched_subtopics属性里,而不是Campaign实例上。所以当你访问campaign.prefetched_subtopics时,这个属性根本不存在,自然返回null。
内容的提问来源于stack exchange,提问作者akash deep

