如何使用Django ORM按双外键条件关联model_B与model_C?
Django ORM实现多条件关联model_B与model_C
我希望以两个条件关联model_B和model_C:model_B的data_a与model_C的data_a匹配,且model_B的human与model_C的author匹配,请问如何通过Django ORM实现该操作?
模型代码
class user(models.Model): data_1 = models.CharField(max_length=60) data_2 = models.SmallIntegerField() data_3 = models.IntegerField(blank=True, null=True) class model_A(models.Model): data_1 = models.CharField(max_length=60) data_2 = models.SmallIntegerField() data_3 = models.IntegerField(blank=True, null=True) class model_B(models.Model): data_a = models.ForeignKey(model_A) human = models.ForeignKey(user) data_2 = models.IntegerField() class model_C(models.Model): data_a = models.ForeignKey(model_A) author = models.ForeignKey(user) data_1 = models.CharField(max_length=5) data_2 = models.IntegerField()
场景1:筛选存在对应model_C的model_B记录
如果只需要找出满足双条件的model_B,用Exists子查询效率最优:
from django.db.models import Exists, OuterRef valid_model_b = model_B.objects.filter( Exists( model_C.objects.filter( data_a=OuterRef('data_a'), author=OuterRef('human') ) ) )
场景2:获取model_B对应的model_C字段值
如果需要把匹配的model_C字段直接映射到model_B的查询结果中,用Subquery实现:
from django.db.models import Subquery, OuterRef # 定义匹配条件的子查询 matched_c = model_C.objects.filter( data_a=OuterRef('data_a'), author=OuterRef('human') ).values('data_1', 'data_2')[:1] # 给model_B添加对应的model_C字段 model_b_with_c = model_B.objects.annotate( c_data1=Subquery(matched_c.values('data_1')), c_data2=Subquery(matched_c.values('data_2')) ) # 示例:遍历获取数据 for item in model_b_with_c: print(f"model_B data_2: {item.data_2}, model_C data_1: {item.c_data1}")
场景3:关联查询两个模型的完整数据
如果需要同时获取model_B和对应model_C的完整数据,通过反向关联+条件过滤实现:
from django.db.models import F # 关联查询满足条件的数据集 joined_data = model_B.objects.filter( data_a__model_c__author=F('human'), data_a__model_c__data_a=F('data_a') ).select_related('data_a', 'human').prefetch_related('data_a__model_c') # 示例:访问关联的model_C数据 for b in joined_data: # 过滤出当前model_B对应的匹配model_C matched_c_list = [c for c in b.data_a.model_c_set.all() if c.author == b.human] for c in matched_c_list: print(f"model_B ID: {b.id}, model_C ID: {c.id}")
说明
- 以上方法均使用Django ORM原生能力,无需手写SQL,保证代码可移植性。
- 若模型设置了
related_name,需将代码中默认反向关联名(如model_c_set)替换为自定义名称。
内容的提问来源于stack exchange,提问作者KIM Bucket
相关产品推荐
相关产品推荐

