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
相关产品推荐
相关产品推荐

