关联查询中with_loader_criteria无法正确过滤非活跃行问题
问题分析与解决方案
核心问题原因
你的_do_orm_execute方法中,orm.with_loader_criteria指定的作用目标是MiscBaseMixin,但A、B、C、D四个模型都没有继承这个Mixin类,所以这个全局过滤规则根本不会对这四个模型生效,自然无法过滤掉is_active=False的行。
解决方案
方案1:让模型继承Mixin类
如果MiscBaseMixin中已经定义了is_active字段,直接让四个模型继承它:
class A(MiscBaseMixin, Base): # 模型字段定义 pass class B(MiscBaseMixin, Base): pass class C(MiscBaseMixin, Base): pass class D(MiscBaseMixin, Base): pass
这样with_loader_criteria的规则会自动应用到所有继承了该Mixin的模型,关联查询时会自动为每个模型添加is_active=True的过滤(关联时会把条件加到JOIN的ON子句,主查询加到WHERE子句)。
方案2:修改_do_orm_execute适配无Mixin的模型
如果不想让模型继承Mixin,可以修改拦截方法,直接指定要过滤的模型:
def _do_orm_execute(execute_state): """拦截所有ORM查询,为指定模型添加过滤规则""" if not any(( execute_state.is_column_load, execute_state.is_relationship_load, execute_state.execution_options.get("include_private", False))): # 定义需要过滤的模型列表 target_models = [A, B, C, D] # 为每个模型添加loader criteria for model in target_models: execute_state.statement = execute_state.statement.options( orm.with_loader_criteria( model, lambda cls: cls.is_active == true(), include_aliases=True, ) )
方案3:手动在查询中添加过滤条件
如果不想修改全局拦截方法,也可以直接在关联查询中手动添加is_active的过滤:
data_getter_query = session.query(A.a_id.label('a_ref'), B.b_id, C.c_id). \ join(D, (D.d_id == A.d_id) & (D.is_active == True)). \ join(B, (B.b_id == D.b_id) & (B.is_active == True), isouter=True). \ join(C, (C.c_id == B.c_id) & (C.is_active == True), isouter=True). \ filter(A.dt_created.isnot(None), A.pan_number == pan_number, A.is_active == True)
注意外连接场景下,要把关联表的is_active条件写在JOIN的ON子句中,避免外连接被转为内连接。
内容的提问来源于stack exchange,提问作者Chetna Bajpai
相关产品推荐
相关产品推荐

