feat: item image now is required

This commit is contained in:
2025-09-21 13:47:19 +08:00
parent 8d12600df4
commit d2ab8d12f6
13 changed files with 1330 additions and 265 deletions
+87
View File
@@ -1,4 +1,27 @@
from django.db import models
import os
import uuid
def get_item_image_path(instance, filename):
"""生成物品图片的存储路径"""
# 如果物品还没有ID,先生成一个临时文件夹名
item_id = instance.item.id if instance.item.id else str(uuid.uuid4())
return f'items/{item_id}/initial/{filename}'
def get_usage_borrow_image_path(instance, filename):
"""生成借用时图片的存储路径"""
item_id = instance.usage.item.id if instance.usage.item.id else str(uuid.uuid4())
usage_id = instance.usage.id if instance.usage.id else str(uuid.uuid4())
return f'items/{item_id}/usage/{usage_id}/borrow/{filename}'
def get_usage_return_image_path(instance, filename):
"""生成归还时图片的存储路径"""
item_id = instance.usage.item.id if instance.usage.item.id else str(uuid.uuid4())
usage_id = instance.usage.id if instance.usage.id else str(uuid.uuid4())
return f'items/{item_id}/usage/{usage_id}/return/{filename}'
class Item(models.Model):
@@ -34,6 +57,23 @@ class Item(models.Model):
return f"{self.name} ({self.serial_number})"
class ItemImage(models.Model):
"""物品图片模型"""
item = models.ForeignKey(Item, on_delete=models.CASCADE, related_name='images', verbose_name='物品')
image = models.ImageField(upload_to=get_item_image_path, verbose_name='图片')
description = models.CharField(max_length=200, blank=True, verbose_name='图片描述')
is_primary = models.BooleanField(default=False, verbose_name='是否为主图')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='上传时间')
class Meta:
verbose_name = '物品图片'
verbose_name_plural = '物品图片'
ordering = ['-is_primary', '-created_at']
def __str__(self):
return f"{self.item.name} - 图片"
class ItemUsage(models.Model):
"""物品使用记录模型"""
item = models.ForeignKey(Item, on_delete=models.CASCADE, verbose_name='物品')
@@ -58,6 +98,53 @@ class ItemUsage(models.Model):
return f"{self.item.name} - {self.user} ({self.start_time.strftime('%Y-%m-%d %H:%M')})"
class UsageImage(models.Model):
"""使用记录图片模型"""
IMAGE_TYPE_CHOICES = [
('borrow', '借用时'),
('return', '归还时'),
]
usage = models.ForeignKey(ItemUsage, on_delete=models.CASCADE, related_name='images', verbose_name='使用记录')
image = models.ImageField(upload_to='usage_images/', verbose_name='图片')
image_type = models.CharField(max_length=10, choices=IMAGE_TYPE_CHOICES, verbose_name='图片类型')
description = models.CharField(max_length=200, blank=True, verbose_name='图片描述')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='上传时间')
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
# 保存后重新组织文件路径
if self.image and self.usage_id and self.usage.item_id:
import os
import shutil
from django.conf import settings
old_path = self.image.path
if self.image_type == 'borrow':
new_relative_path = f'items/{self.usage.item_id}/usage/{self.usage_id}/borrow/{os.path.basename(old_path)}'
else:
new_relative_path = f'items/{self.usage.item_id}/usage/{self.usage_id}/return/{os.path.basename(old_path)}'
new_path = os.path.join(settings.MEDIA_ROOT, new_relative_path)
# 创建目录
os.makedirs(os.path.dirname(new_path), exist_ok=True)
# 移动文件
if os.path.exists(old_path) and old_path != new_path:
shutil.move(old_path, new_path)
self.image.name = new_relative_path
super().save(update_fields=['image'])
class Meta:
verbose_name = '使用记录图片'
verbose_name_plural = '使用记录图片'
ordering = ['-created_at']
def __str__(self):
return f"{self.usage.item.name} - {self.get_image_type_display()}"
class Category(models.Model):
"""物品类别模型"""
name = models.CharField(max_length=50, unique=True, verbose_name='类别名称')