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