Как вручную обновить, создать, удалить поле изображения с помощью сигналов?

Что я хочу сделать: когда я создаю новое изображение, сервер переименовывает фотографию, используя функцию 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

Вернуться на верх