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

Django:如何根据子模型数量总和更新父模型?

Django批量更新父模型quantity为子模型总和的方案

模型定义

class Parent(models.Model):
    id = models.BigAutoField(primary_key=True)
    quantity = models.DecimalField(max_digits=3, decimal_places=0, null=True)

class Child(models.Model):
    parent = models.ForeignKey('Parent', related_name="parent_child", on_delete=models.CASCADE)
    quantity = models.DecimalField(max_digits=3, decimal_places=0, null=True)

需求说明

当Parent模型的quantity字段值不等于其关联Child模型quantity字段的总和时,将Parent的quantity更新为子模型的数量总和。

你已经通过以下代码筛选出了符合更新条件的父模型对象:

parents = Parent.objects.annotate(sum_quantities=Sum('parent_child__quantity')).exclude(quantity=F('sum_quantities'))

(注:代码中Parents应为Parent,修正后如上)

批量更新实现方法

方法一:直接用注解+F表达式(Django 3.2+)

Django 3.2及以上版本支持在update()中直接引用QuerySet的注解字段,写法简洁高效:

from django.db.models import Sum, F

# 筛选并批量更新
Parent.objects.annotate(
    sum_quantities=Sum('parent_child__quantity')
).exclude(quantity=F('sum_quantities')).update(quantity=F('sum_quantities'))

方法二:子查询兼容旧版本

如果使用的是Django 3.2以下版本,需要通过子查询来实现:

from django.db.models import Subquery, OuterRef, Sum

# 定义子查询,获取每个父模型对应的子模型数量总和
child_sum_subquery = Child.objects.filter(parent=OuterRef('pk')).values('parent').annotate(total=Sum('quantity')).values('total')

# 筛选并更新
Parent.objects.annotate(
    sum_quantities=Subquery(child_sum_subquery)
).exclude(quantity=F('sum_quantities')).update(quantity=F('sum_quantities'))

处理无关联子模型的情况

如果部分Parent没有关联的Child,Sum会返回None,导致父模型quantity被设为None。可以用Coalesce设置默认值(比如0):

from django.db.models import Sum, F, Value, DecimalField
from django.db.models.functions import Coalesce

Parent.objects.annotate(
    sum_quantities=Coalesce(Sum('parent_child__quantity'), Value(0, output_field=DecimalField()))
).exclude(quantity=F('sum_quantities')).update(quantity=F('sum_quantities'))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 07:05:19