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

Django小型库存管理应用模型优化与功能扩展技术问询

Django小型库存管理应用模型优化与问题解答

我开发了一款用于管理小型库存的Django应用,核心模型逻辑为:每个Account对应一个Inventory,Inventory中的产品由InventoryProduct维护,库存数量通过Transaction及TransactionItem更新。Transaction分为IN/OUT两种类型,分别对应库存增减,TransactionItem记录单条交易的具体产品与数量。现有models.py代码如下:

class Inventory(models.Model):
    account = models.ForeignKey(
        "accounts.Account", on_delete=models.DO_NOTHING, null=False, blank=False
    )


class InventoryProduct(models.Model):
    inventory = models.ForeignKey("Inventory", on_delete=models.CASCADE)
    sku = models.ForeignKey(
        "products.SKU", on_delete=models.DO_NOTHING, null=False, blank=False
    )
    quantity = models.PositiveIntegerField(
        default=0
    ) 


class Transaction(models.Model):
    IN = 1
    OUT = 0
    TYPE_CHOICES = (
        (IN, "Incoming"),  # 入库
        (OUT, "Outgoing"),  # 出库
    )
    inventory = models.ForeignKey("Inventory", on_delete=models.CASCADE)
    transferred_to = models.ForeignKey(
        "Inventory", on_delete=models.CASCADE, blank=True, null=True
    )
    code = models.UUIDField(default=uuid.uuid4)
    transaction_type = models.PositiveSmallIntegerField(
        choices=TYPE_CHOICES, default=IN
    )
    transaction_date = models.DateTimeField(auto_now_add=True)
    notes = models.TextField(null=True, blank=True)


class TransactionItem(models.Model):
    transaction = models.ForeignKey("Transaction", on_delete=models.CASCADE)
    item = models.ForeignKey("InventoryProduct", on_delete=models.CASCADE)
    quantity = models.IntegerField()

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        self.item.quantity += self.quantity
        self.item.save()

模型优化建议

  • Inventory模型:
    • 新增name字段(如name = models.CharField(max_length=100)),方便区分同一账户下的不同库存(适配未来多仓库扩展场景)。
    • 将on_delete=models.DO_NOTHING改为models.PROTECT或models.CASCADE,避免Account删除后遗留孤立的Inventory记录,引发外键数据不一致问题。
  • InventoryProduct模型:
    • 添加唯一约束,确保同一库存下同一SKU仅存在一条记录:
      class Meta:
          constraints = [
              models.UniqueConstraint(fields=['inventory', 'sku'], name='unique_inventory_sku')
          ]
      
    • 新增库存校验逻辑,避免TransactionItem更新时导致库存变为负数(比如在TransactionItem保存前检查self.item.quantity + self.quantity >= 0)。
  • Transaction模型:
    • 改用Django的TextChoices替代数字枚举,提升代码可读性:
      from django.db import models
      
      class TransactionType(models.TextChoices):
          IN = 'IN', '入库'
          OUT = 'OUT', '出库'
      
      # 修改transaction_type字段:
      transaction_type = models.CharField(
          max_length=3, choices=TransactionType.choices, default=TransactionType.IN
      )
      
    • 可明确inventory为交易的关联库存,transferred_to仅用于转移场景的目标库存,清晰区分普通出库与库存转移。
  • TransactionItem模型:
    • 移除模型内的save重写逻辑,改用post_save信号或业务逻辑层处理库存更新——批量创建TransactionItem时(bulk_create)不会触发模型save方法,会导致库存不更新。示例信号实现:
      from django.db.models.signals import post_save
      from django.dispatch import receiver
      
      @receiver(post_save, sender=TransactionItem)
      def update_inventory_quantity(sender, instance, created, **kwargs):
          if created:
              instance.item.quantity += instance.quantity
              instance.item.save()
      
    • 新增字段校验,比如当交易类型为OUT时,确保quantity为负数,且对应InventoryProduct的库存足够扣减。

技术问题解答

1. 库存间产品转移功能实现与溯源

无需拆分独立的OUT和IN交易,可通过现有模型扩展实现完整转移链路:

  • 转移逻辑:创建一条OUT类型的Transaction,inventory设为来源库存,transferred_to设为目标库存;对应的TransactionItem的quantity设为负数(比如转移5件则填-5)。同时创建一条IN类型的Transaction,inventory设为目标库存,新增related_transaction外键指向之前的OUT交易,用于关联转移记录:
    # 在Transaction模型中添加
    related_transaction = models.ForeignKey(
        'self', on_delete=models.SET_NULL, null=True, blank=True, related_name='linked_transactions'
    )
    
  • 原子性保障:用数据库事务包裹整个转移操作,避免只创建了OUT交易却未创建IN交易的情况:
    from django.db import transaction
    
    def transfer_inventory(source_inventory, target_inventory, sku, quantity):
        with transaction.atomic():
            # 获取来源库存的InventoryProduct
            source_item = InventoryProduct.objects.get(inventory=source_inventory, sku=sku)
            # 创建OUT交易
            out_transaction = Transaction.objects.create(
                inventory=source_inventory,
                transferred_to=target_inventory,
                transaction_type=TransactionType.OUT
            )
            TransactionItem.objects.create(
                transaction=out_transaction,
                item=source_item,
                quantity=-quantity
            )
            # 创建IN交易并关联OUT交易
            target_item, _ = InventoryProduct.objects.get_or_create(inventory=target_inventory, sku=sku)
            in_transaction = Transaction.objects.create(
                inventory=target_inventory,
                related_transaction=out_transaction,
                transaction_type=TransactionType.IN
            )
            TransactionItem.objects.create(
                transaction=in_transaction,
                item=target_item,
                quantity=quantity
            )
    
  • 溯源实现:通过Transaction的related_transaction字段,可直接关联到对应的反向交易,从而追踪产品从哪个库存转出、转入哪个库存,完整还原转移链路。

2. 整合Order到现有模型体系

新增Order相关模型,并与Transaction关联,实现订单入库与库存转移的区分:

  • 新增Order与OrderItem模型:
    class Order(models.Model):
        order_number = models.CharField(max_length=50, unique=True)
        customer = models.ForeignKey('accounts.Account', on_delete=models.CASCADE)
        order_date = models.DateTimeField(auto_now_add=True)
        STATUS_CHOICES = (
            ('PENDING', '待处理'),
            ('COMPLETED', '已完成'),
            ('CANCELLED', '已取消'),
        )
        status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='PENDING')
    
    class OrderItem(models.Model):
        order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='items')
        sku = models.ForeignKey('products.SKU', on_delete=models.CASCADE)
        quantity = models.PositiveIntegerField()
        price = models.DecimalField(max_digits=10, decimal_places=2)
    
  • 关联Transaction与Order:在Transaction模型中添加外键:
    order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True, blank=True, related_name='transactions')
    
  • 业务逻辑整合:
    • 当订单完成入库时,创建IN类型的Transaction,关联对应的Order;TransactionItem可关联对应的OrderItem,实现订单产品到库存交易的追踪。
    • 库存转移的Transaction则不关联Order,以此区分库存的来源是订单还是内部转移。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 20:58:09