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

如何在Django中通过聚合与注解计算购物车商品总价?

使用Django注解与聚合计算订单总价

收到的请求JSON数据格式如下:

{
    "cart":{
        "pizza": 2,
        "burger": 3
     }
}

Food模型定义:

class Food(models.Model):
    name = models.CharField(verbose_name=_('name'), max_length=100, unique=True, blank=False, editable=True)
    price = models.IntegerField(verbose_name=_("maximum price"), null=False, blank=False, editable=True)
    discount = models.PositiveIntegerField(validators=[MaxValueValidator(100)], null=False, blank=False, default=0)
    created_at = models.DateTimeField(verbose_name=_("created time"), auto_now_add=True, editable=False)

现有实现通过for循环计算总价,可改用Django注解与聚合函数优化,直接在数据库层面完成计算:

from django.db.models import Sum, Case, When, IntegerField, F

class OrderView(APIView):
    def post(self, request):
        srz_data = CartSerializer(data=request.data)
        if srz_data.is_valid():
            cart_order = srz_data.data['cart']
            # 构建商品名称与购买数量的匹配规则
            when_clauses = [
                When(name=food_name, then=quantity) 
                for food_name, quantity in cart_order.items()
            ]
            
            # 注解每个商品的购买数量、小计,最后聚合总价
            foods = Food.objects.filter(name__in=cart_order).annotate(
                quantity=Case(*when_clauses, output_field=IntegerField(), default=0)
            ).annotate(
                subtotal=F('price') * F('quantity')
            )
            
            total_price = foods.aggregate(total=Sum('subtotal'))['total'] or 0

关键逻辑说明:

  • Case + When:根据商品名称匹配请求中的购买数量,为每个商品实例添加quantity注解字段
  • F('price') * F('quantity'):用F表达式直接在数据库层面计算单类商品的小计,避免Python与数据库间的数据传输开销
  • Sum('subtotal'):聚合所有商品的小计得到订单总价,or 0用于处理无匹配商品时的空值情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 17:02:33