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

重写Django模型save方法实现购物车逻辑时触发无限循环问题

Django CartItem模型save方法无限循环问题解决方案

问题根因

你重写了CartItem的save方法后,方法内部无论是匹配到已有条目时调用cart_item.save(),还是未匹配到时调用super().save(),都会再次触发你重写的save逻辑,形成递归调用,最终陷入无限循环。

修复方案

这里提供两种可行的实现方式,你可以根据业务场景选择:

方案1:调整save方法逻辑,避免递归调用

仅对新增的实例做合并逻辑处理,已有实例更新直接走父类原生保存逻辑,同时更新已有条目时调用父类save避免二次触发重写逻辑:

import uuid
from django.db import models
from pprint import pprint

class Cart(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self) -> str:
        return str(self.id)

class CartItem(models.Model):
    cart = models.ForeignKey(Cart, on_delete=models.CASCADE, related_name='items')
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField()

    def __str__(self) -> str:
        return self.product.name

    def save(self, *args, **kwargs):
        # _state.adding为True代表当前是未保存的新实例,仅此时走合并逻辑
        if self._state.adding:
            try:
                existing_item = CartItem.objects.get(cart=self.cart, product=self.product)
                existing_item.quantity += self.quantity
                # 直接调用父类save方法保存已有条目,不触发重写的save逻辑
                super(CartItem, existing_item).save(*args, **kwargs)
                pprint(existing_item)
                # 已有条目已更新,直接终止当前新实例的保存流程
                return
            except CartItem.DoesNotExist:
                pprint("-------------------------here")
        # 新增无匹配条目、或更新已有条目时走原生保存逻辑
        super().save(*args, **kwargs)

方案2:抽离合并逻辑到自定义管理器(更推荐)

将购物车条目添加逻辑抽离到模型管理器,避免重写save方法带来的隐式副作用,逻辑更清晰也更易维护:

class CartItemManager(models.Manager):
    def add_to_cart(self, cart, product, quantity):
        item, is_created = self.get_or_create(
            cart=cart,
            product=product,
            defaults={"quantity": quantity}
        )
        if not is_created:
            item.quantity += quantity
            item.save()
        return item

class CartItem(models.Model):
    cart = models.ForeignKey(Cart, on_delete=models.CASCADE, related_name='items')
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField()
    # 绑定自定义管理器
    objects = CartItemManager()

    def __str__(self) -> str:
        return self.product.name

后续需要添加商品到购物车时,直接调用CartItem.objects.add_to_cart(你的cart实例, 你的product实例, 购买数量)即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 17:06:04