Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
Tags
- soft delete
- AWS
- slack
- logstash
- DAG
- 티스토리챌린지
- 논리삭제
- Locust
- Next.js
- docker
- aws ec2
- JWT
- redis
- 계정 관리
- 로그 백업
- hive
- hard delete
- ci/cd
- Hadoop
- node exporter
- Django
- prometheus
- grafana
- Airflow
- nginx
- unique constraint
- NoSQL
- elasticsearch
- 오블완
- 물리삭제
Archives
- Today
- Total
먹수의 개발일지
Django Signals 본문
Intro
유저의 승인 상태 값이 변경(ex.승인대기중 → 승인)되었을때 자동으로 유저에게 승인 완료 메일이 날아가도록 구현하기 위해 사용했다. 임시적으로 django Admin에서 유저의 값을 변경했을 때 해당 기능이 실행되도록 구현해야 했기 때문에, view에서 처리할 수는 없었다.
signal이란
Django 공식문서 Django includes a “signal dispatcher” which helps decoupled applications get notified when actions occur elsewhere in the framework.
Signal은 분리된 어플리케이션의 작업이 발생했음을 알려주고 처리할 수 있는 기능이다. Django signal은 DB 에 값이 저장 직전(pre_save), 저장 후(post_save)에 실행될 작업을 지정 해 줄 수 있다.구현해야할 기능은 저장되기 전에 User의 기존 승인상태값과 비교해야 하기 때문에 pre_save를 사용했다.
한계점
- 디버깅 등 코드 유지관리가 어려울 수 있다.
- 정확한 docs가 되어 있지 않으면, 파일이 분산됨에 따라 signal 함수를 찾기 힘들다. 아래 코드와 같이 user model에 연동되는 signal을 구현했지만, user model에 정의하지 않는 등 찾기 어렵다.
예시 코드
user/signals.py
from django.db.models.signals import pre_save
from django.dispatch import receiver
from utils.send_mail import MailAPI
from user.models import *
def send_approval_email(sender, instance, **kwargs):
"""회원가입 승인&반려 메일
1) 승인 메일 전송
- send mail when User approval HO(대기) or DENY(반려) -> AP(승인)
2) 반려 메일 전송
- send mail when User approval HO(대기) -> DENY(반려)
"""
previous_value = User.objects.get(id = instance.id).approval
current_value = instance.approval
#wait -> deny (반려메일 전송)
if previous_value == UserApproveCode.WAIT and current_value == UserApproveCode.DENY:
email = instance.email
mail_api = MailAPI()
content = mail_api.content_approve(email)
mail_api.send("회원 승인이 반려되었습니다.", content, email)
#wait or deny -> approve(승인메일 전송)
if (previous_value == UserApproveCode.WAIT or previous_value == UserApproveCode.DENY) and current_value == UserApproveCode.APPROVE:
email = instance.email
mail_api = MailAPI()
content = mail_api.content_approve(email)
mail_api.send("승인이 완료되었습니다.", content, email)
@receiver(pre_save, sender=User)
def user_pre_save(sender, instance, **kwargs):
# Check if the instance already exists (updating) & only expert user
if instance.pk and instance.group == UserRoleCode.EXPERT:
send_approval_email(sender, instance, **kwargs)
앱 내부에 app.py에서 ready 메소드를 아래와 같이 오버라이드하여 [앱이름].signals를 import 해준다.
어떤 앱의 AppConfig 가 준비가 되면 실행 되는 메소드가 있는데, 그것이 ready 메소드이다. ready 안에 import 를 넣으면 ready 메소드가 실행이 될 때 import 가 된다.
user/app.py
from django.apps import AppConfig
class UserConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'user'
def ready(self) -> None:
import user.signals
return super().ready()
- user_pre_save라는 함수를 생성하여 instance.pk가 존재할때만 (기존에 저장된 유저가 update 될때만)실행되도록 로직을 추가해주었다.
- send_approval_email은 특정 경우에 승인 메일이 전송되는 함수이다.
- from utils.send_mail import Mail → 별도로 구현한 Mail 모듈을 활용했다.
'back-end > Django' 카테고리의 다른 글
[Django] Redis 캐싱으로 성능 최적화 (0) | 2024.11.20 |
---|---|
[Locust] Django와 Locust로 API 부하 테스트 (1) | 2024.11.19 |
[DRF] Responsed Unauthorized 401 in AllowAny permission (1) | 2023.02.21 |
Comments