Published 2023. 4. 17. 04:47

시그널이란 것을 접하게 된 것은 참 우연찮은 기회인데, 구글 소셜 로그인을 사용하려고 시도했을 당시에 소셜 계정이 생성되는 것은 확인했으나 관련된 모델 인스턴스가 생성되지 않아 어떻게 할지 방법을 찾기 위해서였다.

User 모델에 소셜 계정의 정보가 담기긴 했지만, User 모델 생성시 실행되는 save() 메서드가 호출되지 않아 Profile 모델이 생성되지 않았는데 이유는 잘 모르겠지만 allauth 와 같은 모듈에서 소셜 계정 생성시 User 모델의 save() 메서드를 직접 호출하지 않는다고 판단했다. 그때 찾은 방법이 signal 이었다. signal는 디자인 패턴의 옵저버 패턴을 따른다고 한다.

 

시그널이 좋은 점은 각 컴포넌트들이 이벤트나 변경 사항을 서로에게 통보하기 때문에 느슨하게 코드를 구현할 수 있다. User 모델 내부에 Profile을 생성한다거나 같은 코드를 작성하지 않아도 된다. 각 모델이 독자적으로 존재하고 시그널을 통해 각 모델간의 동작을 이어준다니, 더 깔끔하고 관리하기도 더욱 편해졌다.

pre_save / post_save: 모델 객체가 저장되기 전과 후에 발생하는 시그널
pre_delete / post_delete: 모델 객체가 삭제되기 전과 후에 발생하는 시그널
m2m_changed: ManyToManyField가 변경되었을 때 발생하는 시그널
request_started / request_finished: HTTP 요청이 시작되거나 완료될 때 발생하는 시그널

 

위는 검색하여 나온 시그널들이다. 이번에 내가 사용한 시그널은 post_save인데 이를 이용하여 User모델이 생성되는 이벤트 이후에 지정해줄 수 있었다. 나는 User 모델 생성시 User 모델을 Profile의 user field에 연결하여 모델 인스턴스를 생성하도록 하였고, 잘 작동하였다.

from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Profile


@receiver(post_save, sender=get_user_model())
def create_profile(sender, instance, created, **kwargs):
    if created:
        profile = Profile(user=instance)
        profile.save()

receiver 라는 데코레이터를 이용하여 내가 만든 create_profile을 post_save 시그널에 연결해주었다. created arg를 통해 create 이벤트 판단이 가능하다. 이 코드를 signals.py라는 새 파일을 만들어 기입하였고. 이 시그널을 인식시키기 위해 아래와 같은 설정을 추가적으로 해야했다.

 

#__init__.py
default_app_config = 'user.UserConfig'

#app.py
from django.apps import AppConfig

class UserConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "user"
    
    def ready(self):
        import user.signals

__init__.py에 app config를 app.py 내부 클래스로 지정하여 def ready라는 함수를 통해 signals.py를 임포트하는 거라고 생각한다.

 

자세한 내용은 공식 docs를 참고하자.

https://docs.djangoproject.com/en/4.2/ref/signals/

 

Django

The web framework for perfectionists with deadlines.

docs.djangoproject.com

 

'Python > Django' 카테고리의 다른 글

DRF : Serializer  (0) 2023.04.23
django : generic view  (0) 2023.04.17
Django : 역참조, queryset  (0) 2023.04.07
나의 첫 Django Project : community - 5 -  (0) 2023.03.23
나의 첫 Django Project : community - break -  (0) 2023.03.21
복사했습니다!