在Django中保存InventoryOpenings时更新WarehouseStockStatus表
问题解决:期初库存录入同步更新库存状态表
模型定义
# models.py class Warehouse(models.Model): site_name = models.CharField(max_length=100) class Item(models.Model): item = models.CharField(max_length=100) class WarehouseStockStatus(models.Model): site_name = models.ForeignKey(Warehouse, on_delete=models.CASCADE) item = models.ForeignKey(Item,on_delete=models.CASCADE,editable = False) class Meta: unique_together = ("site_name", "item") stock_opening_quantity = models.PositiveBigIntegerField( default = 0, editable = False ) stock_consumption_quantity = models.PositiveBigIntegerField( default = 0, editable = False ) current_inventory_level = models.PositiveBigIntegerField( default = 0, editable = False ) class InventoryOpenings(models.Model): site_name = models.ForeignKey(Warehouse, on_delete=models.CASCADE,related_name='openings') transaction_number = models.BigAutoField(primary_key = True, serialize = False) class InventoryOpeningsDetails(models.Model): transaction_number = models.ForeignKey(InventoryOpenings, on_delete=models.CASCADE) item = models.ForeignKey(Item,on_delete=models.CASCADE) opening_quantity = models.PositiveBigIntegerField( default = 0, editable = True )
业务需求
Warehouse表与WarehouseStockStatus表为一对多关系,Item表用于库存管理。通过InventoryOpenings和InventoryOpeningsDetails表录入仓库商品期初库存数量时,需同步更新WarehouseStockStatus表中对应仓库-商品组合的stock_opening_quantity和current_inventory_level字段,将录入的期初数量累加至对应字段。
当前代码问题分析
你之前的代码存在几个关键错误:
- 直接查询整个表取第一条数据,未关联当前保存的期初库存单据实例
- 使用
filter返回QuerySet,无法直接赋值字段,且DoesNotExist异常对filter不生效(空QuerySet不会抛出异常) - 直接操作模型类字段而非实例字段,无法获取实际数值进行累加
- 循环保存时错误操作QuerySet而非单个实例
修正后的Admin代码
class InventoryOpeningsDetailsInline(admin.TabularInline): model = InventoryOpeningsDetails extra = 1 class InventoryOpeningsAdmin(admin.ModelAdmin): inlines = [InventoryOpeningsDetailsInline] def save_model(self, request, obj, form, change): super().save_model(request, obj, form, change) self._sync_stock_status(obj) def save_formset(self, request, form, formset, change): super().save_formset(request, form, formset, change) if formset.model == InventoryOpeningsDetails: self._sync_stock_status(form.instance) def _sync_stock_status(self, inventory_opening): # 获取当前单据下的所有库存明细 details = inventory_opening.inventoryopeningsdetails_set.all() target_warehouse = inventory_opening.site_name for detail in details: target_item = detail.item add_quantity = detail.opening_quantity # 自动处理库存状态记录的创建/更新 WarehouseStockStatus.objects.update_or_create( site_name=target_warehouse, item=target_item, defaults={ # 数据库层面累加数值,避免并发问题 'stock_opening_quantity': models.F('stock_opening_quantity') + add_quantity, 'current_inventory_level': models.F('current_inventory_level') + add_quantity } )
代码说明
- 关联当前单据:通过当前保存的期初库存实例获取对应明细,确保操作的是本次录入的数据
- update_or_create简化逻辑:自动处理库存状态记录存在/不存在的场景,无需手动捕获异常
- F()表达式:直接在数据库层面完成数值累加,避免并发更新导致的数据不一致问题
- 覆盖双保存方法:同时处理主表保存和明细表单集保存的情况,确保新增/修改操作都能触发库存同步
内容的提问来源于stack exchange,提问作者Mahinder Pal Singh Ahuja
相关产品推荐
相关产品推荐

