오히려 좋아..

상황이 나쁘게만 흘러가는 것 같을 때 외쳐보자.. .

궁금한 마음으로 포트폴리오 보기

Web Programming/Django

[Django] 이미지 파일업데이트시 기존 파일 삭제하기

junha6316 2021. 3. 8. 13:53

 

1. 직접 구현

원하는 모델의 save method를 아래와 같이 오버라이드 해주면 된다.

import sys

class Blablabla(model.model):

    def save(self, *args, **kwargs):
         #해당하는 model 클래스를 갖고온다.
        mod = getattr(sys.modules[__name__], self._meta.object_name)

        try:
            obj = mod.objects.get(id=self.id)
        except:
            obj = None
        else:
            for field in obj._meta.fields:
                field_type = field.get_internal_type()

        #필드 이름이 FileField나 ImageField 라면
        if field_type == 'FileField' or field_type == 'ImageField':
            origin_file = getattr(obj, field.name)
            new_file = getattr(self, field.name)
            #기존 필드랑 새로운 필드를 비교해서 다르다면 삭제해준다
            if origin_file != new_file:

            #그냥 url을 사용하면 경로를 못찾는다.
            path = '.' + origin_file.url
            if os.path.isfile(path):
                os.remove(path)

        super(mod, self ).save(*args, **kwargs)
        return

code.djangoproject.com/ticket/6157

 

#6157 (Code to delete files when updating a filefield) – Django

I'm using this code in my custom the save() methods. It looks for a filefield or imagefield, and delete the previous file when you insert a new one. Perhaps it could be a good idea to include it by defauly inside the save method of the object. from django.

code.djangoproject.com

2. 패키지 사용하기

github.com/un1t/django-cleanup

 

un1t/django-cleanup

Automatically deletes old file for FileField and ImageField. It also deletes files on models instance deletion. - un1t/django-cleanup

github.com

3. Signal 사용하기(가장 추천하는 방법)

from django.db import models

class Event(models.model):

	planImage = models.ImageField("행사계획 이미지", upload_to=ImageDirectory, height_field=None, width_field=None, blank=True, null=True)
	buttonImage = models.ImageField("버튼 이미지", upload_to=ImageDirectory, height_field=None, width_field=None, max_length=None, help_text="등록하기 버튼 이미지 입니다.(필수항목) 권장 사이즈:400 x 120")
	footerImage = models.ImageField("바닥 이미지", upload_to=ImageDirectory, height_field=None, width_field=None, null=True, help_text="등록페이지의 바닥에 위치하는 이미지 입니다.(필수항목) 권장 사이즈: 1200 x 75")
	regCompleteImage = models.ImageField("등록 완료 이미지", upload_to=ImageDirectory, height_field=None, width_field=None, null=True, help_text="등록을 완료하면 보이는 이미지 입니다.(필수항목) 권장 사이즈:1000 x 500")
	endImage = models.ImageField("행사 종료 이미지", upload_to=ImageDirectory, height_field=None, width_field=None, help_text="행사가 종료된 후 띄어지는 이미지 입니다.(필수항목) 권장 사이즈:800 x 400")

@receiver(models.signals.pre_save, sender=Event)
def auto_delete_file_on_save(sender, instance, **kwargs):
    if not instance.pk:
        return False
    try:
        old_obj = sender.objects.get(pk=instance.pk)
    except sender.DoesNotExist:
        return False

    for field in instance._meta.fields:
        field_type = field.get_internal_type()
        if field_type == 'FileField' or field_type == 'ImageField':
            origin_file = getattr(old_obj, field.name)
            new_file = getattr(instance, field.name)
            print(origin_file, new_file)
            if origin_file != new_file and os.path.isfile(origin_file.path):
              
                os.remove(origin_file.path)


@receiver(models.signals.post_delete, sender=Event)
def auto_delete_file_on_delete(sender, instance, **kwargs):
    for field in instance._meta.fields:
        field_type = field.get_internal_type()
        if field_type == 'FileField' or field_type == 'ImageField':
            origin_file = getattr(instance, field.name)
            if origin_file and os.path.isfile(origin_file.path):
                os.remove(origin_file.path)