westagram # 3. decorator

11499 단어 djangodjango

decorator를 처음 써보면서 어려웠던 점에 대해 기록하고자 한다. 😢

1. 파일 생성

우선 touch decorator.py 로 파일을 만들어 줍니다.

# decorator.py
import json, jwt, bcrypt

from django.core import exceptions
from django.http import JsonResponse
from django.core.exceptions import ObjectDoesNotExist

from my_settings import SECRET_KEY
from user.models import Account

class login_decorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, request, *args, **kwargs):
        try:
            access_token = request.headers.get('authorization')
            payload = jwt.decode(access_token, SECRET_KEY, algorithms = 'HS256')
            user    = Account.objects.get(id=payload['account_id'])
            request.user = user
            return self.func(self, request, *args, **kwargs)

        except Account.DoesNotExist:
            return JsonResponse({"MESSAGE":"INVALID_USER"}, status=401)

decorator를 class로 하는 사람도 있었고 def로만 만드는 사람도 있었다. 나는 이 중에 class 로 만들었다.

def trace(func):                             # 호출할 함수를 매개변수로 받음
    def wrapper():                           # 호출할 함수를 감싸는 함수
        print(func.__name__, '함수 시작')    # __name__으로 함수 이름 출력
        func()                               # 매개변수로 받은 함수를 호출
        print(func.__name__, '함수 끝')
    return wrapper                           # wrapper 함수 반환

2. class와 init

기본적으로 decorator의 구조는 이렇다.

데코레이터 login_decorator는 호출할 함수를 매개변수로 받습니다. 그리고 호출할 함수를 만들었습니다.
근데 제가 적은 decorator는 wrapper() 대신에 __init__이 들어가서 당황하신 분이 있을거라 생각합니다.

우선 class에 대해 알 필요가 있습니다. class는 무엇인가를 똑같은 형태로 만들어 낼 수 있는 틀이라고 생각하시면 됩니다.

물론 def로만 함수를 정의해서 만들 수 있지만, 저희는 scrum 방식을 생각해 재사용성이 쉽게 될 수 있도록 해야합니다.

추가적인 기능 추가를 위해서 클래스를 만드는 것이 효율적이기 때문에 class를 사용한 것입니다.

3. init의 역할

호출할 함수를 인스턴스의 초깃값으로 받아야할 때 사용한다.

  • 컨스트럭터라고 불리는 초기화를 위한 함수(메소드)
  • 인스턴스화를 실시할 때 반드시 처음에 호출되는 특수한 함수
  • 오브젝트 생성(인스턴스를 생성)과 관련하여 데이터의 초기를 실시하는 함수

init()은 반드시 첫 번째 인수로 self를 지정해야한다. self에는 인스턴스 자체가 전달되어 있다. 클래스를 생성할 때에 지정한 인수는 초기화 메소드의 2번째부터 작성이 가능해진다.

4. __call__

access_token을 request의 headers에서 authorization을 가져온다. 여기서 'authorization'은 프론트와 상의해서 이름을 가져온다.

request.objects는 objects, headers, body 등 정해져있는 것이 있는데 가져오고 싶을 것을 넣는다.

5. views.py

class FollowView(View):
    @login_decorator
    def post(self, request):
        try:
            data = json.loads(request.body)
            signed_user = request.user
            if Follow.objects.filter(following=signed_user, follower_id=data['follower']).exists():
                Follow.objects.filter(following=signed_user, follower_id=data['follower']).delete()
            Follow.objects.create(
                following = signed_user,
                follower_id = data['follower']
            )
            return JsonResponse({"MESSAGE":"SUCCESS"}, status=201)
        except KeyError:
            return JsonResponse({"MESSAGE":"KEY_ERROR"}, status=400)

참고자료

decorator 이론 - 코딩도장
https://dojang.io/mod/page/view.php?id=2430

class를 사용하는 이유
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=n2ll_&logNo=221442949008

__init__ 이란?
https://engineer-mole.tistory.com/190

좋은 웹페이지 즐겨찾기