Django中如何根据关联外键的modelA实例id过滤查询modelD元素
实现方案
Django ORM原生支持通过双下划线__跨外键关系做连表过滤,针对你这个三层外键关联的场景,直接用跨关系查询是性能最高、代码最简洁的方案,不需要逐层查询关联模型。
推荐写法(单条SQL查询,性能最优)
如果你已知目标modelA的主键id值,直接在modelD的查询集上用双下划线追溯外键链路即可:
# 替换target_a_id为你实际拿到的modelA记录id target_a_id = 1 d_queryset = modelD.objects.filter(C__B__A_id=target_a_id)
字段链路的逻辑很直白:
- 第一层
C对应modelD上关联modelC的外键字段 - 第二层
C__B对应从modelC追溯到关联的modelB外键字段 - 第三层
C__B__A_id对应从modelB直接匹配关联modelA的主键id,这里直接用A_id而不是A可以省去一次连A表的操作,查询效率更高。
如果你已经提前拿到了modelA的实例对象,也可以直接传实例做过滤,ORM会自动匹配主键:
a_instance = modelA.objects.get(id=target_a_id) d_queryset = modelD.objects.filter(C__B__A=a_instance)
注意事项
- 如果你在定义外键时手动指定了
related_name参数,只需要把链路中对应位置的字段名替换成你自定义的反向关系名即可。 - 不要写逐层查B、再查C、最后查D的逻辑,这类写法会产生多次数据库请求,数据量稍大就会有明显的性能问题,反面示例如下:
# 反面示例:不推荐,会产生多次数据库查询,性能差 b_qs = modelB.objects.filter(A_id=target_a_id) c_qs = modelC.objects.filter(B__in=b_qs) d_qs = modelD.objects.filter(C__in=c_qs)
内容的提问来源于stack exchange,提问作者user14596364
相关产品推荐
相关产品推荐

