Django如何使用Prefetch对象关联两个查询集并解决字段找不到问题
问题1解答
你对prefetch_related的作用存在误解:
prefetch_related的to_attr是ORM给返回的模型实例添加的Python层面的属性,仅存在于内存中的模型对象上,不会被识别为数据库可查询字段。你调用.values()时Django只会解析数据库层存在的字段,自然找不到test属性。- 同时对
signal_value使用select_related和Prefetch属于冗余操作:select_related会通过JOIN直接从数据库拉取关联的SignalValue数据,此时Prefetch定义的额外查询不会生效。 - 如果你坚持用
Prefetch方案,需要去掉.values()调用,直接遍历返回的ResultSignal实例,才能访问到test属性拿到注解字段。
问题2解答
完全不需要额外关联两个QuerySet,也不需要用RawSQL或者Pandas内存处理,ORM原生支持你需要的逻辑:
你可以直接把SignalValue的过滤、注解逻辑合并到ResultSignal的主查询中,所有计算都在数据库侧执行,效率和原生SQL一致。参考代码如下:
result_signals = ( last_interview_result .resultsignal_set .filter( signal_value__in=signal_values_of_interest, filter_aggregator # 直接复用你原来的SignalValue过滤规则,ORM会自动识别关联路径 ) .select_related( 'signal_value__signalvaluecategory__signal_category', 'signal_value__signalvaluesubcategory__signal_subcategory', 'signal_value__signalvaluetype__signal_type', 'signal_value__signalvaluesubtype__signal_subtype', ) .annotate( # 直接复用你原来的注解逻辑,涉及SignalValue的字段统一加signal_value__前缀即可 filter_group_id=Window( expression=DenseRank(), order_by=group_filters ), filter_group_name=filter_name_case ) .values( "signal_value", "filter_group_id", "filter_group_name", category=F('signal_value__signalvaluecategory__signal_category__name'), subcategory=F('signal_value__signalvaluesubcategory__signal_subcategory__name'), type=F('signal_value__signalvaluetype__signal_type__name'), subtype=F('signal_value__signalvaluesubtype__signal_subtype__name'), ) )
如果你的过滤、注解逻辑复用场景多,可以把filter_aggregator、group_filters、filter_name_case封装成独立的Q对象、表达式变量,不需要重复编写。仅当遇到ORM完全无法表达的极端复杂SQL逻辑时,再考虑使用RawSQL。
内容的提问来源于stack exchange,提问作者MetaHG
相关产品推荐
相关产品推荐

