View Decorator
๐ก View Decorator
Decorator๋ ์ด๋ค ํจ์๋ฅผ ๊ฐ์ธ๋(Wrapping)ํ๋ ํจ์์ด๋ค.
function๊ณผ class์๋ง ์ ์ฉ์ด ๊ฐ๋ฅํ๋ค. ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์๋ค.
#-- case1
@login_required
def test_view1(request):
return render(request, 'instagram/test.html')
#-- case2
def test_view2(request):
return render(request, 'instagram/test.html')
test_view = login_required(test_view2)
๐ก django ๊ธฐ๋ณธ decorator
django.views.decorator.http
โฃ ๐ ์์ค ์ฝ๋
๋ทฐ๊ฐ ํน์ ์์ฒญ ๋ฉ์๋๋ง ํ์ฉํ๋๋ก ํ๋ ๋ฐ์ฝ๋ ์ดํฐ๋ค.
์ฌ์ฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ๋ค.
@require_http_method(["GET", "POST"])
def test_view(request):
pass
# Decorator to require that a view only accepts the GET method.
require_GET = require_http_methods(["GET"])
# Decorator to require that a view only accepts the POST method.
require_POST = require_http_methods(["POST"])
# Decorator to require that a view only accepts safe methods: GET and HEAD.
require_safe = require_http_methods(["GET", "HEAD"])
์ง์ method๊ฐ ์๋ ๊ฒฝ์ฐ, HttpResponseNotAllowed ์๋ต (์ํ์ฝ๋ 405) ๋ฐํํ๋ค.
django.contrib.auth.decorators
โฃ ๐ ์์ค ์ฝ๋
โ user_passes_test
์ฌ์ฉ์๊ฐ ์ฃผ์ด์ง ํ ์คํธ๋ฅผ ํต๊ณผํ๋์ง ํ์ธํ๋ ๋ทฐ์ฉ ๋ฐ์ฝ๋ ์ดํฐ,
ํ์ํ ๊ฒฝ์ฐ ๋ก๊ทธ์ธ ํ์ด์ง๋ก ๋ฆฌ๋๋ ์ ํฉ๋๋ค.
ํ ์คํธ๋ ํธ์ถ ๊ฐ๋ฅํด์ผ ํ๋ฉฐ ์ฌ์ฉ์ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ค๊ณ ์ฌ์ฉ์๊ฐ ํต๊ณผํ๋ฉด True๋ฅผ ๋ฐํํฉ๋๋ค.
โ login_requires
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ๋์ง ํ์ธํ๋ ๋ทฐ์ฉ ๋ฐ์ฝ๋ ์ดํฐ, ๋ฆฌ๋๋ ์ ํ์ํ ๊ฒฝ์ฐ ๋ก๊ทธ์ธ ํ์ด์ง๋ก ์ด๋ํฉ๋๋ค
โ permission_required
์ฌ์ฉ์์๊ฒ ํน์ ๊ถํ์ด ์๋์ง ํ์ธํ๋ ๋ณด๊ธฐ์ฉ ๋ฐ์ฝ๋ ์ดํฐ ํ์ํ ๊ฒฝ์ฐ ๋ก๊ทธ์ธ ํ์ด์ง๋ก ๋ฆฌ๋๋ ์ ํฉ๋๋ค.
raise_exception ๋งค๊ฐ๋ณ์์ PermissionDenied ์์ธ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ ์ ๊ธฐ๋๋ค.
๐ก CBV์ decorator ์ฌ์ฉํ๊ธฐ
#-- Case1 : ์์ฒญ์ ์ฒ๋ฆฌํ๋ ํจ์๋ฅผ wrappingํ๊ธฐ โ ๊ฐ๋
์ฑ Bad
from django.contrib.auth.decorators import login_required
from django.views.generic import TempalteView
class SecretView(TemplateView):
template_name = 'myapp/secret.html'
view_fn = SecretView.as_view()
secret_view = login_required(view_fn)
#-- Case2 : ํด๋์ค ๋ฉค๋ฒํจ์์ method_decorator๋ฅผ ํ์ฉ
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TempalteView
class SecretView(TemplateView):
template_name = 'myapp/secret.html'
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)
secret_view = SecretView.as_view()
#-- Case3 : ํด๋์ค์ ์ง์ ์ ์ฉ
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TempalteView
@method_decorator(login_required, name='dispatch')
class SecretView(TemplateView):
emplate_name = 'myapp/secret.html'
secret_view = SecretView.as_view()
CBV๋ฅผ ์ฌ์ฉํ ๋ LoginRequiredMixin์ ์ฌ์ฉํ์ฌ login_required์ ๋์ผํ ๋์์ ์ป์ ์ ์์ต๋๋ค.
ํด๋น ๋ฏน์ค์ธ์ ์์ ๋ชฉ๋ก์์ ๊ฐ์ฅ ์ผ์ชฝ์ ์์ด์ผ ํฉ๋๋ค.
โฃ ๐ ๊ด๋ จ docs
#-- LoginRequiredMixin ์ ์ฉ
from djangno.contib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView
class TestListView(LoginRequiredMixin,ListView):
model = Post
template_name = 'instagram/post_list.html'
pagenate_by = 10