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

Django图书借阅系统:借还图书时库存增减逻辑实现问题

解决方案

1. 借阅逻辑:创建借阅记录时扣减库存

在Borrowing模型的save方法中,判断当前是否为新创建的记录,若是则调用关联图书的库存扣减方法,同时增加库存不足的校验逻辑,避免负库存出现。

示例代码:

# models.py
from django.db import models
from django.core.exceptions import ValidationError
from django.db import transaction

class Book(models.Model):
    title = models.CharField(max_length=200)
    inventory = models.IntegerField(default=0)

    def reduce_inventory_book(self):
        if self.inventory <= 0:
            raise ValidationError("图书库存不足,无法借阅")
        self.inventory -= 1
        self.save()

    def increase_inventory_book(self):
        self.inventory += 1
        self.save()

class Borrowing(models.Model):
    book = models.ForeignKey(Book, on_delete=models.CASCADE)
    borrow_date = models.DateTimeField(auto_now_add=True)
    expected_return_date = models.DateTimeField()
    actual_return_date = models.DateTimeField(null=True, blank=True)

    def save(self, *args, **kwargs):
        with transaction.atomic():
            # 处理借阅:新创建记录时扣减库存
            is_new = self.pk is None
            if is_new:
                self.book.reduce_inventory_book()
            
            # 处理归还:更新时填充了actual_return_date且之前未填充
            if not is_new:
                old_borrowing = Borrowing.objects.get(pk=self.pk)
                if old_borrowing.actual_return_date is None and self.actual_return_date is not None:
                    self.book.increase_inventory_book()
            
            super().save(*args, **kwargs)

2. 替代方案:用Django信号处理归还逻辑

如果不想在save方法中堆砌过多逻辑,可以使用post_save信号监听Borrowing的更新事件,触发库存增加操作。

示例代码:

# signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Borrowing
from django.db import transaction

@receiver(post_save, sender=Borrowing)
def handle_book_return(sender, instance, created, **kwargs):
    if not created:
        with transaction.atomic():
            old_instance = sender.objects.get(pk=instance.pk)
            if old_instance.actual_return_date is None and instance.actual_return_date is not None:
                instance.book.increase_inventory_book()

需要在apps.py中注册信号:

# apps.py
from django.apps import AppConfig

class YourAppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'your_app_name'

    def ready(self):
        import your_app_name.signals

3. 原create方法未生效的原因排查

  • create方法仅处理新增记录的逻辑,而归还操作是更新现有记录,所以不会触发该逻辑。
  • 未使用事务包裹操作,可能出现并发场景下的库存数据不一致问题。

4. 额外注意事项

  • 操作库存时必须保证原子性,避免多用户同时操作导致库存异常。
  • 可以在视图层或表单层提前校验图书库存,避免在模型层抛出异常影响用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 14:25:30