장고 - Signal 학습

Signal이란?

  • 특정 액션이 발생하면 그 후에 발생하는 이벤트 (django를 포함한 여러 프레임워크에 존재)
  • 저장하기 전/후, 삭제하기 전/후 등 특정 signal이 웹 어플리케이션에 전달
  • 예로, 회원가입 후 ‘축하합니다’ 메일 보낼 때 signal이 사용된다.
  • Signal 종류
    • pre_save : 저장 전, 실행
    • post_save : 저장 후, 실행
    • pre_delete : 삭제 전, 실행
    • post_save : 삭제 후, 실행



post_delete 구현해보기

  • 이전에 학습했던 dstagram 프로젝트를 예시로 들어보자.

    • 특정 포스트 삭제 후, s3에 저장된 데이터 삭제

      경로 : dstagram_project > photo > views.py

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      from django.db.models.signals import post_delete
      from django.dispatch import receiver


      import boto3
      from django.conf import settings


      @receiver(post_delete, sender=Photo)
      # 어떤 종류의 시그널이 발생했고, 어디서 보냈는지를 명시
      def post_delete(sender, instance, **kwargs):
      # 메서드 이름은 자유이며, sender와 **kwargs를 매개변수로 받아온다.
      # instance : 현재 저장된 바로 그 instance
      # kwargs는 signal 종류마다 그 내용이 다르다.

      # s3 연결한 다음에 object 사진 지울 것
      session = boto3.Session(
      aws_access_key_id = settings.AWS_ACCESS_KEY_ID,
      aws_secret_access_key = settings.AWS_SECRET_ACCESS_KEY,
      region_name = settings.AWS_REGION
      )


      s3 = session.resource('s3')

      # s3.Object는 s3에 업로드된 파일 객체를 얻어오는 클래스
      # arg1 = 버킷 이름
      # arg2 = 파일 경로 - Key (버킷 실제 경로는 media/ 에 있으므로 "media/" 추가)
      image = s3.Object(settings.AWS_STORAGE_BUCKET_NAME, "media/" + str(instance.image))
      image.delete()
  • 조금 더 간단한 방법을 사용하자면 아래와 같다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    from django.db.models.signals import post_delete
    from django.dispatch import receiver

    import boto3
    from django.conf import settings

    @receiver(post_delete, sender=Photo)
    def post_delete(sender, instance, **kwargs): # 메서드 이름은 상관없다. **kwargs만 붙여라
    # s3 연결한 다음에 object의 사진 지울 것
    # instance 는 그 포스트의 메모리 주소
    storage = instance.image.storage
    # s3에 저장된 데이터들은 path로 찾을 수 없고, key 로 찾아야 한다.
    if storage.exists(str(instance.image)): # media storage가 "media/" 붙여서 만들어준다.
    storage.delete(str(instance.image))