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
相关产品推荐
相关产品推荐

