12. class based views 이해 - chohankyun/python-django-study GitHub Wiki

##class based views
모든 뷰는 요청을 받고, 응답을 리턴한다, 라는 것으로 볼때,
단순하게 함수로만으로 제공하는것 보다는 큰 틀을 만들어서
그 틀을 재사용하고, 그 틀에 맞게 코드를 작성하므로써 좀 더
구조적인 코드가 되도록 한다.(django documentation 나름대로 해석)

all views class ->(상속) View class
View class 기능

  • url 링크 처리
  • http method 에 따른 함수 호출
  • etc..

##class based views 호출 방법
app/urls.py => as_view() : 클래스 함수 호출(entry point)

from django.conf.urls import url  
from django.views.generic import TemplateView

urlpatterns = [
    # urls 에서 제너릭 클래스 직접 호출(첫번째 방법)  
    url(r'^about/$', TemplateView.as_view(template_name="about.html")),
    url(r'^books/$', BookListView.as_view()),
]

app/views.py

from django.views.generic import ListView
from books.models import Book
 

# 클래스 상속(두번째 방법, 속성 또는 함수 오버라이드)    
class BookListView(ListView):
    model = Book

##class based views 특징

  • 조건(ex: if 문, ect..)에 의한 분기 보다 HTTP method(ex: get, post, ect..) 에 따른 분기로 함수 호출
  • 객체 지향 프로그래밍, mixins(다중 상속)의 사용으로 코드 재활용

##generic views(미리 만들어진 뷰, 개발 편의성)

  • function-based generic views
  • Class-based generic views

##class based views 기본 함수

  • as_view() : entry point 모든 Class-based generic views 는 as_view() 부터 시작(클래스 메쏘드)
  • dispatch() : http method(get, post, etc.) 를 이용해서 함수 호출

##class based views, function based views 비교
HTTP GET 일 경우
function based views

app/urls.py

from django.conf.urls import url
from myapp import views 

urlpatterns = [
    url(r'^about/$', views.my_view),
]

app/views.py

from django.http import HttpResponse  

def my_view(request):  
    if request.method == 'GET': # request 에서 method 값으로 분기   
        # <view logic>  
        return HttpResponse('result')  

class based views

app/urls.py

from django.conf.urls import url
from myapp.views import MyView

urlpatterns = [
    url(r'^about/$', MyView.as_view()),
]

app/views.py

from django.http import HttpResponse
from django.views import View


class MyView(View):
    def get(self, request): # as_view() -> dispatch() 함수에서 get() 함수 호출
        # <view logic>
        return HttpResponse('result')  

##decorating class based views
class based views 확장 방법

  • mixins
  • decorators

##mixins

  • generic calss based views 사용(django 제공 class)
  • custom class based views 사용(사용자 개발 class)

##decorators
decorator urls.py 적용
method decorator : @method_decorator
as_view() 를 decorating
decorator : login_required, permission_required
request 가 있을때 마다 만들어지는 instance 별 적용
같은 함수를 사용하는 두개의 요청(두개의 url)이 있고
하나의 요청에만 decorator 를 사용하면, decorator 를
사용한 요청의 instance 만 적용

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

from .views import VoteView

urlpatterns = [
    url(r'^about/$', login_required(TemplateView.as_view(template_name="secret.html"))),
    url(r'^vote/$', permission_required('polls.can_vote')(VoteView.as_view())),
]

decorator 클래스 적용
함수에 직접 적용
decorator : login_required
decorator 가 적용된 함수가 호출 될때 마다 적용

첫번째 방법: 클래스 안에 있는 함수에 적용

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


class ProtectedView(TemplateView):
    template_name = 'secret.html'

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

두번째 방법: 클래스 상단에서 name 속성(name=함수)을 이용한 적용

@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'

새번째 방법: 여러개의 decorator 적용은 decorator list 사용
순서: 왼쪽부터 오른쪽으로 적용

decorators = [never_cache, login_required]

@method_decorator(decorators, name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'
⚠️ **GitHub.com Fallback** ⚠️