You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Django ORM实现多表关联查询与聚合操作?

Django ORM 实现多层关联模型的聚合查询需求

模型定义

以下是嵌套关联的Django模型结构(实际层级可能更多或更少):

class ModelA(models.Model):
    value = models.IntegerField()

class ModelB(models.Model):
    modelA = models.ForeignKey(ModelA, on_delete=models.CASCADE)
    value = models.IntegerField()

class ModelC(models.Model):
    modelB = models.ForeignKey(ModelB, on_delete=models.CASCADE)
    value = models.IntegerField()

class ModelD(models.Model):
    modelC = models.ForeignKey(ModelC, on_delete=models.CASCADE)
    value = models.IntegerField()

class ModelE(models.Model):
    modelD = models.ForeignKey(ModelD, on_delete=models.CASCADE)
    value = models.IntegerField()

# 更多层级...

基础查询示例

1. 查询指定ModelA对应的所有ModelE

SQL等价语句:

SELECT ModelE.*
FROM ModelA
JOIN ModelB ON ModelB.modelA = ModelA.id
JOIN ModelC ON ModelC.modelB = ModelB.id
JOIN ModelD ON ModelD.modelC = ModelC.id
JOIN ModelE ON ModelE.modelD = ModelD.id
WHERE ModelA.id = 1

Django ORM实现:

ModelE.objects.filter(modelD__modelC__modelB__modelA_id=1)

2. 按ModelC分组并聚合ModelE的value

SQL等价语句:

SELECT ModelC.*, SUM(ModelE.value)
FROM ModelA
JOIN ModelB ON ModelB.modelA = ModelA.id
JOIN ModelC ON ModelC.modelB = ModelB.id
JOIN ModelD ON ModelD.modelC = ModelC.id
JOIN ModelE ON ModelE.modelD = ModelD.id
WHERE ModelA.id = 1
GROUP BY ModelC.id

Django ORM实现:

from django.db.models import Sum

ModelC.objects.filter(
    modelB__modelA_id=1
).annotate(
    sum_e_value=Sum('modelD__modelE__value')
).values('id', 'value', 'sum_e_value')

具体需求:计算ModelC.value与ModelE.value总和的乘积

用户需要实现等价于以下SQL的高效查询,替代低效的Python workaround:
SQL等价语句:

SELECT ModelC.value * SUM(ModelE.value)
FROM ModelA
JOIN ModelB ON ModelB.modelA = ModelA.id
JOIN ModelC ON ModelC.modelB = ModelB.id
JOIN ModelD ON ModelD.modelC = ModelC.id
WHERE ModelA.id = 1 AND ModelD.value >= 1 AND ModelD.value < 3
GROUP BY ModelC.id

高效Django ORM实现

利用Django的F()表达式和聚合函数,直接在数据库层面完成计算,避免Python内存中处理数据:

from django.db.models import Sum, F

result = ModelC.objects.filter(
    modelB__modelA_id=1,
    modelD__value__gte=1,
    modelD__value__lt=3
).annotate(
    sum_e_value=Sum('modelD__modelE__value')
).annotate(
    calculated_result=F('value') * F('sum_e_value')
).values('id', 'calculated_result')

说明

  • 使用F()表达式直接引用数据库字段进行运算,所有计算逻辑在数据库端完成,避免了将大量数据加载到Python内存后再处理,大幅提升效率。
  • 通过双层annotate,先聚合得到sum_e_value,再基于该聚合值和ModelC.value计算最终结果。
  • filter中的多层关联查询modelB__modelA_id和modelD__value__gte/lt,对应SQL中的JOIN和WHERE条件。

内容的提问来源于stack exchange,提问作者IbbyStack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 15:25:17