상세페이지의 update,delete를 위한 소유권 확인

  1. 상세페이지의 pk 가져오기

urls.py

urlpatterns = [
    path(
        "update/<int:pk>",
        ArticleUpdateView.as_view(),
        name="update",
    ),
    path(
        "delete/<int:pk>",
        ArticleDeleteView.as_view(),
        name="delete",
    ),
]
  1. decorator 생성시 글 작성자와 로그인한 유저가 동일한지 확인

decorators.py

from django.http import HttpResponseForbidden

from articleapp.models import Article


def article_ownership_required(func):
    def decorated(request, *args, **kwargs):
        article = Article.objects.get(pk=kwargs["pk"])
        if not article.writer == request.user:
            return HttpResponseForbidden()
        return func(request, *args, **kwargs)

    return decorated
  1. view에서 실제로 적용하기

views.py

@method_decorator(article_ownership_required, "get")
@method_decorator(article_ownership_required, "post")
class ArticleUpdateView(UpdateView):
    model = Article
    form_class = ArticleCreationForm
    context_object_name = "target_article"
    template_name = "articleapp/update.html"

    def get_success_url(self):
        return reverse("articleapp:detail", kwargs={"pk": self.object.pk})
  1. 리스트형태로 decorator 가져오기 가능

views.py


# decorators.py에서 사용할 decorator를 가져와 리스트에 삽입
has_owership = [login_required, article_ownership_required]

@method_decorator(has_owership, "get")
@method_decorator(has_owership, "post")
class ArticleUpdateView(UpdateView):
    model = Article
    form_class = ArticleCreationForm
    context_object_name = "target_article"
    template_name = "articleapp/update.html"

    def get_success_url(self):
        return reverse("articleapp:detail", kwargs={"pk": self.object.pk})
728x90

decorator

decorator ?

함수를 받아 명령을 추가한 뒤 이를 다시 함수의 형태로 반환하는 함수이다.
함수의 내부를 수정하지 않고 기능에 변화를 주고 싶을 때 사용한다 .
일반적으로 함수의 전처리나 후처리에 대한 필요가 있을때 사용을 한다.
또한 데코레이터를 이용해, 반복을 줄이고 메소드나 함수의 책임을 확장한다

decorator는 원래 작업의 앞 뒤에 추가적인 작업을 손쉽게 사용 가능하도록 도와주는 역할

데코레이터의 구조

함수형

def out_func(func):  # 기능을 추가할 함수를 인자로

    def inner_func(*args, **kwargs):

        return func(*args, **kwargs)

    return inner_func

example

# decorator 정의
def decorator(func):
    def wrapper(*args, **kwargs):

        print('전처리')   
        print(func(*args, **kwargs))
        print('후처리')
    return wrapper

# decorator 사용
@decorator
def example():
    return '함수'

#############
example()
'''''''''
전처리
함수
후처리
'''''''''

클래스형

class Decorator:

    def __init__(self, function):
        self.function = function

    def __call__(self, *args, **kwargs):
        return self.function(*args, **kwargs)

example

class Decorator:

    def __init__(self, function):
        self.function = function

    def __call__(self, *args, **kwargs):
        print('전처리')
        print(self.function(*args, **kwargs))
        print('후처리')

@Decorator
def example():
    return '클래스'

example()
'''''''''
전처리
클래스
후처리
'''''''''

django decorator

FBV

from django.contrib.auth.decorators import login_required
from django.shortcuts import render

# 방법 1
@login_required
def post_create(request):
  # 생략
  return render(request, 'core/index.html')


# 방법 2
def post_create(request):
  # 생략
  return render(request, 'core/index.html')

post_create = login_required(post_create)

CBV

방법 3 추천

# 방법 1

from django.contrib.auth.decorators import login_required
from django.views.generic import TemplateView

class MyTemplateView(TemplateView):
    template_name= "core/index.html"

index = MyTemplateView.as_view()
index = login_required(index)

# 방법 2

from django.utils.decorators import method_decorator

class MyTemplateView(TemplateView):
    template_name= "core/index.html"

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
      return super().dispatch(*args, **kwargs)

index = MyTemplateView.as_view()

# 방법 3

@method_decorator(login_required, name="dispatch")
class MyTemplateView(TemplateView):
    template_name= "core/index.html"


index = MyTemplateView.as_view()
728x90

+ Recent posts