Django 1.11:能否用prefetch_related关联D、B表并做字段比对?
嘿,这个需求完全可以搞定!在Django 1.11里,咱们可以借助Prefetch对象配合OuterRef来定制预取的查询逻辑,从而实现获取所有D对象的同时,预取出和它字段匹配的B对象。下面给你详细说怎么做:
核心思路
因为D和B都关联到A模型,所以每个D对象对应的A下会有一组B对象。我们需要在预取B的时候,额外筛选出和当前D对象指定字段匹配的那些B,这就需要用Prefetch来定义自定义的预取查询集,并用OuterRef引用外部D对象的字段做比对。
具体代码实现
首先假设你要比对的是D和B的name字段(如果是其他字段,直接替换即可),代码如下:
from django.db.models import Prefetch, OuterRef # 定义预取的B查询集:筛选与当前D同属一个A、且name字段匹配的B对象 matching_b_queryset = B.objects.filter( a=OuterRef('a'), # 确保B和D属于同一个A name=OuterRef('name') # 匹配D和B的name字段 ) # 查询所有D对象,并预取符合条件的B d_objects = D.objects.all().prefetch_related( Prefetch( 'a__b', # 通过D的a外键,关联到A的b集合(B的related_name是b) queryset=matching_b_queryset, to_attr='matching_b' # 把筛选后的B对象存到D的自定义属性里,方便访问 ) )
如何访问结果
预取完成后,你可以直接通过自定义属性matching_b访问每个D对象对应的匹配B:
for d in d_objects: print(f"D名称: {d.name}") print("匹配的B对象:") for b in d.matching_b: print(f"- {b.name}")
注意事项
- 如果你的匹配字段不是
name,只需要把name=OuterRef('name')替换成对应的字段即可,比如code=OuterRef('code')。 to_attr参数很重要,它会把筛选后的B集合存到自定义属性中,不会覆盖原有的a__b集合,避免混淆。- Django 1.11已经支持
OuterRef,所以这个方案完全兼容你的版本。
内容的提问来源于stack exchange,提问作者Anuj
相关产品推荐
相关产品推荐

