Как вручную обновить, создать, удалить поле изображения с помощью сигналов?
Что я хочу сделать: когда я создаю новое изображение, сервер переименовывает фотографию, используя функцию image_name, при обновлении удаляет старое и создает новое, при удалении только удаляет файл, удаление работает, а другие нет
Я хочу сделать это хорошим способом, потому что я пытался использовать upload_to
с os
и pathlib
либами, чтобы сделать это, но я думаю, что могу создать это лучше с помощью хранилищ, поэтому я ничего не кодирую
Модели :
class Product(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50, null=False, blank=False)
describtion = models.TextField()
price = models.FloatField()
inventory = models.PositiveIntegerField()
created_time = models.DateTimeField(auto_now_add=True)
last_updated_time = models.DateTimeField(auto_now=True)
labels = models.ManyToManyField(
Label, through="ProductLabels", through_fields=( "product","label")
)
categories = models.ManyToManyField(
Category, through="ProductCategories", through_fields=( "product","category")
)
objects = ProductManager()
def __str__(self) -> str:
return self.name
def get_absolute_url(self) -> str:
return reverse("products:product", kwargs={"pk": self.pk})
@property
def photos(self):
return ProductImage.objects.filter(product=self)
@property
def base_photo(self):
photos = self.photos
if photos:
return photos.first().image
class ProductImage(models.Model):
id = models.AutoField(primary_key=True)
image = models.ImageField(storage=select_storage)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
# base = models.BooleanField(default=True)
def __str__(self) -> str:
return self.product.name
Хранилища:
from django.core.files.storage import FileSystemStorage , Storage
from django.conf import settings
product_photos_storage = FileSystemStorage(location=f"{settings.MEDIA_ROOT}/products/photos")
# TODO add the Remote Storage
def select_storage()->Storage:
return product_photos_storage
сигналы:
from django.db.models.signals import post_delete , post_save , pre_save
from django.dispatch import receiver
from .models import ProductImage
from django.core.files import File
from django.conf import settings
from .storages import select_storage
def image_name(obj:ProductImage)->str:
return f"{obj.product.name}-{obj.id}.jpg"
# This Work On Delete
@receiver(post_delete, sender=ProductImage)
def my_handler(sender,instance:ProductImage, **kwargs):
storage = select_storage()
file_name = instance.image.name
if storage.exists(file_name):
storage.delete(file_name)
@receiver(pre_save, sender=ProductImage)
def my_handler(sender,instance:ProductImage, **kwargs):
storage = select_storage()
file_name = ProductImage.objects.filter(id=instance.id) or None
if file_name:
if storage.exists(file_name.first().image.name):
storage.delete(file_name.first.image.name)
@receiver(post_save, sender=ProductImage)
def update_image_path(sender, instance:ProductImage, created,**kwargs):
if created:
storage = select_storage()
new_name = image_name(instance)
instance.image.name = new_name
storage.save(content=instance.image,name=image_name(instance))
instance.save()
Я получаю эту ошибку при создании изображения :
[Errno 13] Permission denied