如何在PonyORM的LEFT JOIN的ON子句中添加条件?
在PonyORM中实现带ON子句额外条件的LEFT JOIN
你遇到的问题很典型——PonyORM里使用导航属性(比如af.RoleAccess)加if过滤时,这个条件会被自动放到WHERE子句里,而不是LEFT JOIN的ON子句,这就会丢失左表中没有匹配右表的行,不符合你想要的左连接效果。
要实现把ra.roleid = 2放到ON子句里,你需要直接对两个实体进行左连接,并把所有连接条件都写在left_join的推导式中,而不是用导航属性的过滤。
正确的代码实现
假设你的RoleID是一个关联实体,ra.RoleID.RoleID对应数据库中的roleid字段,目标角色ID为2,可以这样写:
from pony.orm import left_join target_role_id = 2 # 定义左连接,将所有连接条件放在推导式的if中 query = left_join( (af.AppFormID, af.AppFormTitle, ra.CreateGrant, ra.ReadGrant, ra.UpdateGrant, ra.DeleteGrant, ra.PrintGrant) for af in AppForms for ra in RoleAccess if ra.AppFormID == af.AppFormID and ra.RoleID.RoleID == target_role_id ) # 执行查询并获取结果 results = list(query)
为什么这样可行?
当你使用left_join直接连接两个实体(AppForms和RoleAccess)时,推导式中的if条件会被PonyORM解析为LEFT JOIN的ON子句条件,而不是WHERE子句。这样就能保留AppForms中的所有行,即使对应的RoleAccess不存在或者roleid不等于2,这些行的RoleAccess字段值会是None。
对比原来的写法问题
你之前的代码:
query= orm.left_join((af.AppFormID, af.AppFormTitle, ra.CreateGrant, ra.ReadGrant, ra.UpdateGrant, ra.DeleteGrant, ra.PrintGrant) for af in AppForms for ra in af.RoleAccess if ra.RoleID.RoleID == id)
这里的for ra in af.RoleAccess if ...是对af的导航属性RoleAccess进行过滤,PonyORM会把这个过滤条件放到WHERE子句,导致最终结果只保留那些存在匹配roleid=2的RoleAccess的AppForms行,丢失了左表中没有匹配的行,这就不符合左连接的预期了。
内容的提问来源于stack exchange,提问作者Mahyar Esteki
相关产品推荐
相关产品推荐

