Django中如何更新外键关联模型字段实现库存扣减
问题核心原因
你当前代码无法更新库存的直接原因是:修改了关联stockList实例的quantity_in_store属性后,没有调用save()方法将修改持久化到数据库,内存中的字段变更不会自动同步到库。除此之外你的实现还存在几个会导致数据错误的隐患:
- 仅覆盖了新增出库单的场景,没有处理出库单修改、删除时的库存回滚/重算逻辑
- 没有并发控制,多用户同时操作同一商品出库时会出现超卖、库存数据不准的问题
- 没有库存合法性校验,出库量大于在库量时会出现负库存
可直接落地的实现代码
将admin.py中的代码替换为以下内容即可:
from django.db import transaction from django.contrib import admin from django.contrib import messages from .models import stockList, stockOut class StockoutAdmin(admin.ModelAdmin): list_display = ["staff_name", "stock", "shipping_qty", "shipping_company"] @transaction.atomic def save_model(self, request, obj, form, change): # 记录修改前的旧出库数量,用于编辑场景的库存差值计算 old_shipping_qty = 0 if change: old_stockout = stockOut.objects.select_for_update().get(pk=obj.pk) old_shipping_qty = old_stockout.shipping_qty or 0 # 加行锁查询对应库存,避免并发超卖 target_stock = stockList.objects.select_for_update().get(pk=obj.stock.pk) new_shipping_qty = obj.shipping_qty or 0 # 计算本次实际需要调整的库存值 adjust_qty = new_shipping_qty - old_shipping_qty if target_stock.quantity_in_store < adjust_qty: messages.error(request, "当前在库库存不足,无法完成出库操作") return # 更新库存并持久化 target_stock.quantity_in_store -= adjust_qty target_stock.save() # 保存出库单记录 super().save_model(request, obj, form, change) @transaction.atomic def delete_model(self, request, obj): # 删除出库单时回滚对应库存 target_stock = stockList.objects.select_for_update().get(pk=obj.stock.pk) target_stock.quantity_in_store += obj.shipping_qty or 0 target_stock.save() super().delete_model(request, obj)
关键逻辑说明
- 用
@transaction.atomic装饰器开启数据库事务,保证库存调整和出库单增删改两个操作要么全部成功,要么全部回滚,不会出现数据不一致 select_for_update()会给查询到的库存行加排他锁,事务提交前其他操作无法修改这条库存记录,从根源避免并发超卖问题- 兼容出库单编辑场景:修改已有出库单的出库数量时,只调整新旧数量的差值,不会重复扣减库存
- 新增删除出库单的库存回滚逻辑,避免误删出库单导致库存数据永久错误
- 增加库存合法性校验,拦截会导致负库存的出库操作
内容的提问来源于stack exchange,提问作者joyce
相关产品推荐
相关产品推荐

