You need to enable JavaScript to run this app. Django中如何关联三张表并自动填充汇总计算结果的新表
优惠活动
大模型
产品
解决方案
定价
更多

Django中如何关联三张表并自动填充汇总计算结果的新表

Django实现三表关联按name汇总number的方案

第一步:定义模型类

首先按照你给出的表结构定义对应的Django模型,通过外键关联三张表(若为存量表无法修改结构可调整为手动关联逻辑,以下为Django标准实现):

from django.db import models

# 表A模型
class TableA(models.Model):
    code = models.CharField(max_length=32, unique=True, verbose_name="A表编码")
    name = models.CharField(max_length=32, verbose_name="名称")
    class Meta:
        db_table = "table_a"

# 表B模型
class TableB(models.Model):
    code_a = models.ForeignKey(TableA, to_field="code", on_delete=models.CASCADE, db_column="code_A", related_name="b_items")
    code = models.CharField(max_length=32, unique=True, verbose_name="B表编码")
    class Meta:
        db_table = "table_b"

# 表C模型
class TableC(models.Model):
    code_b = models.ForeignKey(TableB, to_field="code", on_delete=models.CASCADE, db_column="code_B", related_name="c_items")
    number = models.IntegerField(verbose_name="数值")
    class Meta:
        db_table = "table_c"

# 物理存储的汇总表模型(不需要落库可以不定义)
class SummaryTable(models.Model):
    name = models.CharField(max_length=32, unique=True, verbose_name="名称")
    number = models.IntegerField(default=0, verbose_name="汇总数值")
    class Meta:
        db_table = "summary_table"

第二步:直接查询获取汇总结果(无需物理存储汇总表)

如果不需要把汇总结果持久化到数据库,直接用Django ORM的聚合查询即可得到你要的结果:

from django.db.models import Sum, F

# 直接查询得到汇总数据,结构和你预期的结果完全一致
summary_data = TableA.objects.annotate(
    total_number=Sum("b_items__c_items__number")
).values(
    "id", "name", number=F("total_number")
)

第三步:自动填充物理汇总表(需要落库时使用)

如果需要把汇总结果存入单独的汇总表,可根据业务需求选择以下两种自动更新方案:

方案1:定时任务批量更新(适合实时性要求不高的场景)

可以用Django自定义命令+系统定时任务,或者Celery定时执行以下同步逻辑:

def sync_summary_data():
    # 拉取最新汇总数据
    summary_list = TableA.objects.annotate(
        total=Sum("b_items__c_items__number")
    ).values("name", "total")
    # 批量更新或创建汇总记录
    for item in summary_list:
        SummaryTable.objects.update_or_create(
            name=item["name"],
            defaults={"number": item["total"] or 0}
        )

方案2:信号触发实时更新(适合实时性要求高的场景)

通过Django信号监听表C的增删改操作,只要数据变动就自动更新对应汇总记录:

# 信号定义(可单独放在signals.py文件中)
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from django.db.models import Sum

@receiver([post_save, post_delete], sender=TableC)
def update_summary_when_c_change(sender, instance, **kwargs):
    # 获取当前变动记录关联的表A实例
    a_instance = instance.code_b.code_a
    # 重新计算该维度的总和
    total = TableC.objects.filter(
        code_b__code_a=a_instance
    ).aggregate(total=Sum("number"))["total"] or 0
    # 更新汇总表
    SummaryTable.objects.update_or_create(
        name=a_instance.name,
        defaults={"number": total}
    )

信号需要在应用的apps.py中注册才能生效:

from django.apps import AppConfig

class YourAppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = '你的应用名称'

    def ready(self):
        import 你的应用名称.signals # 导入存放信号的文件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 03:48:00