如何在Django中从两个关联表获取数据?附关联模型代码
嘿,我来帮你搞定Django里关联表的数据检索问题~首先先提下你模型里的几个小细节(不影响功能但更规范):
IntegerField不需要设置max_length参数,所以size和quantity字段的max_length可以删掉price字段没写完,建议用DecimalField(decimal_places=2, max_digits=10)这类适合存储金额的字段- 外键字段名改成
purchase会比p_id更符合Django的命名习惯,不过这不会影响查询逻辑
接下来分几种常用场景给你演示如何跨关联表检索数据:
1. 从采购单(主表)获取对应的所有商品(子表)
因为你的外键定义在Purchased_Items模型中,Django会自动给Purchases模型添加一个反向关联属性,默认是模型名小写_set,也就是purchased_items_set:
# 先获取一个采购单实例 purchase = Purchases.objects.get(p_id=1) # 获取该采购单对应的所有商品 all_items = purchase.purchased_items_set.all() # 遍历输出商品信息 for item in all_items: print(f"商品:{item.item},数量:{item.quantity},单价:{item.price}")
如果你觉得默认的反向关联名不够直观,可以在定义外键时加上related_name参数自定义:
# 修改Purchased_Items的外键定义 p_id = models.ForeignKey(Purchases, on_delete=models.CASCADE, related_name='items')
之后就可以用更简洁的方式获取关联商品:
all_items = purchase.items.all()
2. 从商品(子表)获取对应的采购单(主表)
这个更直接,每个Purchased_Items实例都可以直接通过外键字段p_id访问关联的采购单对象:
# 获取一个商品实例 item = Purchased_Items.objects.get(id=1) # 获取该商品对应的采购单 purchase = item.p_id # 打印采购单日期 print(f"采购日期:{purchase.date.strftime('%Y-%m-%d')}")
3. 跨表过滤查询
你可以通过双下划线__跨关联表设置过滤条件:
- 例1:查询2023年10月1日之后的采购单对应的所有商品
from datetime import date target_date = date(2023, 10, 1) items = Purchased_Items.objects.filter(p_id__date__gte=target_date)
- 例2:查询包含特定商品(比如"牛奶")的所有采购单
# 如果没设置related_name,用默认的反向关联名 purchases = Purchases.objects.filter(purchased_items_set__item='牛奶') # 如果设置了related_name='items',则写成 purchases = Purchases.objects.filter(items__item='牛奶')
4. 优化查询性能(避免N+1问题)
当你批量查询数据时,如果循环访问关联对象,会触发多次数据库查询(也就是N+1问题),可以用以下方法优化:
- 从子表查主表时,用
select_related预加载关联的主表数据:
# 获取所有商品,同时预加载对应的采购单,避免每次访问item.p_id都查数据库 items = Purchased_Items.objects.all().select_related('p_id')
- 从主表查子表时,用
prefetch_related预加载关联的子表数据:
# 获取所有采购单,同时预加载对应的所有商品 purchases = Purchases.objects.all().prefetch_related('purchased_items_set') # 如果设置了related_name='items',则写成 purchases = Purchases.objects.all().prefetch_related('items')
内容的提问来源于stack exchange,提问作者Rafa
相关产品推荐
相关产品推荐

