2

在我当前的项目中,我将图像存储在 s3 存储桶中。我有一个 pre_save 信号接收器,可以从 Image 类的 s3 存储桶中删除实际图像。

class Image(models.Model):
    name = models.CharField(max_length = 255)
    caption = models.CharField(max_length = 255)
    image = models.ImageField(upload_to='uploads/',blank=True,null=True)
    rent_property = models.ForeignKey(RentProperty, related_name='Images')
    is_main_image = models.BooleanField(default=False)

@receiver(models.signals.pre_save, sender=Image)
def auto_delete_file_on_change(sender, instance, **kwargs):
    """Deletes file from filesystem
    when corresponding `MediaFile` object is changed.
    """
    if not instance.pk:
        return False

    try:
        old_file = Image.objects.get(pk=instance.pk).image
    except Image.DoesNotExist:
        return False

    new_file = instance.image
    if not old_file == new_file:
        old_file.delete(save=False)

我的问题是,我正在使用 django-rest-framework,我想让 PATCH 工作。但是,例如,如果我尝试修补图像描述,它将删除图像本身。我的问题是,我如何编写一个可以区分天气的 IF 补丁中是否存在需要更改的新图像,如果没有,则什么也不做?

4

1 回答 1

2

对于具有 ImageField 或 FileField 的模型,我包含一个附加字段来存储 SHA-1 哈希字符串。我发现这很有用,原因有很多:

  • 减少相同文件的不必要传输以进行更新(您的情况)
  • 防止用户上传重复文件作为新实例
  • 在下载文件时为用户提供 SHA-1 哈希,以便他们可以验证下载
  • 在后端文件系统上进行数据完整性检查以验证文件没有更改

我还保存了原始文件名,以便为面向用户的视图/下载重现它。这样,后端名称对用户来说就无关紧要了。

这是基于您的模型的基本实现:

import hashlib
from django.core.exceptions import ValidationError
from django.core.files import File
from django.db import models

class Image(models.Model):
    name = models.CharField(max_length = 255)
    caption = models.CharField(max_length = 255)
    image = models.ImageField(upload_to='uploads/',blank=True,null=True)
    original_filename = models.CharField(
        unique=False,
        null=False,
        blank=False,
        editable=False,
        max_length=256)
    sha1 = models.CharField(
        unique=True,
        null=False,
        blank=False,
        editable=False,
        max_length=40)
    rent_property = models.ForeignKey(RentProperty, related_name='Images')
    is_main_image = models.BooleanField(default=False)

    def clean(self):
        """
        Overriding clean to do the following:
            - Save  original file name, since it may already exist on our side.
            - Save SHA-1 hash and check for duplicate files.
        """

        self.original_filename = self.image.name.split('/')[-1]
        # get the hash
        file_hash = hashlib.sha1(self.image.read())
        self.sha1 = file_hash.hexdigest()

        # Check if this file has already been uploaded,
        # if so delete the temp file and raise ValidationError
        duplicate_hashes = Image.objects.all().exclude(
                id=self.id).values_list('sha1', flat=True)
        if self.sha1 in duplicate_hashes:
            if hasattr(self.image.file, 'temporary_file_path'):
                temp_file_path = self.image.file.temporary_file_path()
                os.unlink(temp_file_path)

            raise ValidationError(
                "This image already exists."
            )
于 2014-05-22T13:47:35.233 回答