Django如何使用prefetch_related实现多层级反向关系数据预取
问题原因
你写的prefetch_related多层级关联查询本身是生效的,看不到更深层缓存的原因是:Django的预取结果只会挂载在对应关联层级的实例上:
carnivore_set是TestParams的直接反向关联,所以缓存存在TestParams实例的_prefetched_objects_cache中animal、metrics_set是Carnivore的关联对象,它们的预取结果存在每个Carnivore实例的_prefetched_objects_cache中,不会直接挂载到根TestParams实例上,所以你打印TestParams的__dict__看不到这两项。
验证预取生效的方法
你可以通过以下方式确认深层关联已经被成功预取,访问时不会触发额外SQL:
for test_param in test_params_data: # 遍历TestParams关联的所有Carnivore for carnivore in test_param.carnivore_set.all(): # 访问animal、metrics_set不会触发新的数据库查询 print(carnivore.animal.name) print(carnivore.metrics_set.all()) # 打印Carnivore实例的缓存就能看到对应数据 print(carnivore._prefetched_objects_cache.keys())
更高效的写法优化
因为Carnivore到Animal是正向外键关联,用select_related(单表JOIN查询)比prefetch_related(额外单独查询)性能更好,你可以用Prefetch对象更清晰地控制预取逻辑:
from django.db.models import Prefetch test_params_data = TestParams.objects.filter(**filters).prefetch_related( Prefetch( "carnivore_set", queryset=Carnivore.objects.select_related("animal").prefetch_related("metrics_set") ) )
这种写法和你原来的双下划线写法效果完全一致,只是逻辑更清晰,也方便你后续给Carnivore、metrics_set加额外过滤条件。
内容的提问来源于stack exchange,提问作者user001
相关产品推荐
相关产品推荐

