2

現在のプロジェクトでは、画像を s3 バケットに保存しています。Image クラスの s3 バケットから実際の画像を削除する pre_save シグナル レシーバーがあります。

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 に答える