OS | Ubuntu 16.04.4 LTS | ||
VERSION | python 3.5.2 | ||
Django 2.1.2 |
* 다음 내용은 한빛미디어 파이썬 웹프로그래밍 책을 재정리한 것입니다.
요약
- Django에서 클래스형 뷰를 사용하면 코드가 깔끔해지고 코드의 재사용성이나 개발 생산성을 높여준다.
- 클래스형 뷰의 상속 기능을 이용하기 위해서는 제네릭 뷰에 대해 이해해야 한다.
- 제네릭 뷰는 크게 Base View, Generic Edit View, Generic Display View, Generic Date View로 나눌 수 있다.
클래스형 뷰
URLconf에서 클래스형 뷰 사용을 표시해야 한다.
장고의 URL 해석기는 요청과 관련된 파라미터들을 클래스가 아닌 함수에 전달한다.
때문에, 클래스형 뷰는 클래스 진입을 위한 진입 메소드를 제공한다. 위의 예제에서의 as_view()와 같은 메서드이며, 아래의 순서로 요청을 처리한다.
MyView 클래스는 View 클래스의 상속을 받는다.
View 클래스에는 as_view()와 dispatch()가 정의되어 있으므로 정의하지 않아도 사용할 수 있다.
# urls.py
from django.conf.urls import path
from myapp.views import MyView
urlpatterns = [
path('about/', MyView.as_view()),
]
장고의 URL 해석기는 요청과 관련된 파라미터들을 클래스가 아닌 함수에 전달한다.
때문에, 클래스형 뷰는 클래스 진입을 위한 진입 메소드를 제공한다. 위의 예제에서의 as_view()와 같은 메서드이며, 아래의 순서로 요청을 처리한다.
- as_view() 클래스의 인스턴스를 생성한다.
- 생성된 인스턴스의 dispatch() 메소드를 호출한다.
- dispatch() 메소드는 요청을 검사해서 어떤 HTTP 메소드(GET, POST)가 요청되었는지 알아낸다.
- 인스턴스 내의 해당 이름을 갖는 메소드로 요청을 중계한다.
- 해당 메소드가 정의되어 있지 않다면, HttpResponseNotAllowed 익셉션을 발생시킨다.
# views.py
from django.http import HttpResponse
from django.views.generic import View
class MyView(View):
def get(self, request):
# 뷰 로직 작성
return HttpResponse('result')
View 클래스에는 as_view()와 dispatch()가 정의되어 있으므로 정의하지 않아도 사용할 수 있다.
클래스형 뷰의 장점
- GET, POST 등의 HTTP 메소드에 따른 처리 기능을 코딩할 때, IF 함수를 사용하지 않고 메소드명으로 구분할 수 있으므로 코드의 구조가 깔끔해진다.
- 다중 상속과 같은 객체 지향 기술이 가능하므로, 클래스형 제네릭 뷰 및 믹스인 클래스 등을 사용할 수 있고, 이는 코드의 재사용성이나 개발 생산성을 높여준다.
클래스형 뷰가 HTTP 메소드(GET, POST, HEAD 등)의 요청을 수신한 후 어떻게 처리하고 함수형 뷰와 어떻게 다른지 비교해보자. 함수형 뷰는 아래와 같은 로직을 작성한다.
from django.http import HttpResponse
def my_view(request):
if request.method == 'GET':
# 뷰 로직 작성
return HttpResponse('result')
함수형 뷰에서는 요청 메소드의 속성을 체크하는 로직이 필요하기 때문에, 항상 if 조건의 체크문이 필요하다. 하지만 클래스형 뷰를 사용하면 다음과 같이 깔끔해진다.
# views.py
from django.http import Httpresponse
from django.views.generic import View
class MyView(View):
def get(self, request):
# 뷰 로직 작성
return HttpResponse('result')
클래스형뷰에서는 HTTP 메소드 이름으로 클래스에 메소드를 정의하면 된다. 단, 메소드명은 소문자로 해야 한다.
이는, 클래스형 내부에 존재하는 dispatch() 메소드가 GET, POST 등의 어떤 HTTP 메소드로 요청되었는지를 알아낸 다음 해당 이름을 갖는 메소드로 요청을 중계해주기 때문에 가능한 것이다.
상속 기능 가능
우리가 작성하는 클래스형 뷰의 대부분은 제네릭 뷰를 상속받아 작성하므로, 상속 기능을 이해하려면 제네릭 뷰에 대해 알아야 한다.
# some_ app/urls.py
from django.urls import path
from some_app.views import AboutView
urlpatterns = [
path('about/', AboutView.as_view()),
]
#some_app/views.py
from django.views.generic import TemplateView
class AboutView(TemplateView):
template_name = "about.html"
제네릭 뷰란, 뷰 개발 과정에서 공통으로 사용할 수 있는 기능들을 추상화하여, 장고에서 미리 만들어 제공해주는 클래스형 뷰를 말한다. 제네릭 뷰를 상속받아 클래스형 뷰를 작성하는 예제를 살펴보자.
views.py 파일의 소스가 2줄로 로직을 완성할 수 있는 이유는 TemplateView 라는 제네릭 뷰를 사용하고 있기 때문이다.
TemplateView 는 뷰에 특별한 로직이 없고, URL 에 맞춰 해당 템플릿 파일의 내용만 보여줄 때 사용하는 제네릭 뷰이다. 따라서, 다음과 같이 URLconf 작성만으로 위와 같은 역할을 수행할 수도 있다.
# some_app/urls.py
from django.urls import path
from django.views.generic import TemplateView
urlpatterns = [
path('about/', TemplateView.as_view(template_name="about.html")),
]
클래스형 제네릭 뷰
Django에서 제공하는 제네렉 뷰는 다음과 같이 4가지로 분류할 수 있다.
- Base View : 뷰 클래스를 생성하고, 다른 제네릭 뷰의 부모 클래스를 제공하는 기본 제네릭 뷰
- Generic Display View : 객체의 리스트를 보여주거나, 특정 객체의 상세 정보를 보여줌
- Generic Edit View : 폼을 통해 객체를 생성, 수정, 삭제하는 기능을 제공
- Generic Date View : 날짜 기반 객체의 연/월/일 페이지로 구분해서 보여줌
Django의 제네릭 뷰 리스트(일부)
Base View
- View : 가장 기본의 최상위 제네릭 뷰
- TemplateView : 템플릿이 주어지면 해당 템플릿을 렌더링 해줌
- RedirectView : URL이 주어지면 해당 URL로 리다이렉트 해줌
- ListView : 조건에 맞는 여러 개의 객체를 보여줌
- DetailView : 객체 하나에 대한 상세한 정보를 보여줌
- FormView : 폼이 주어지면 해당 폼을 보여줌
- CreateView : 객체를 생성하는 폼을 보여줌
- UpdateView : 기존 객체를 수정하는 폼을 보여줌
- DeleteView : 기존 객체를 삭제하는 폼을 보여줌
- ArchiveIndexView : 조건에 맞는 여러 개의 객체 및 그 객체들에 대한 날짜 정보를 보여줌
- YearArchiveView : 연도가 주어지면 그 연도에 해당하는 객체들을 보여줌
- MonthArchiveView : 연, 월이 주어지면 그에 해당하는 객체들을 보여줌
- WeekArchiveView : 연도와 주차(week)가 주어지면 그에 해당하는 객체들을 보여줌
- TodayArchiveView : 오늘 날짜에 해당하는 객체들을 보여줌
- DateDetailView : 연, 월, 일 기본키(또는 슬러그)가 주어지면 그에 해당하는 특정 객체 하나에 대한 상세한 정보를 보여줌
클래스형뷰에서 폼 처리
폼 처리 과정은 아래와 같이 3가지 경우로 구분할 수 있다.
from .forms import MyForm
동일한 로직을 클래스형 뷰로 코딩해보자.
from django.views.generic import View
from .forms import MyForm
class MyFormView(View):
form_class = MyForm
initial = {'key': 'value'}
template_name = 'form_template.html'
def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
# cleaned_data로 관련 로직 처리
return render(request, self.template_name, {'form': form})
클래스형 뷰에서는 HTTP 의 GET 방식과 POST 방식을 클래스 내의 메소드로 구분하여 처리했기 때문에 구조가 깔끔해진다.
이 코드를 폼 처리용 제네릭 뷰인 FormView를 상속받아 처리하면 코드가 훨씬 간단해진다.
코딩의 내용이 훨씬 단순해졌는데, 다음의 4가지 사항을 유의해 코딩하면 된다.
- 최초의 GET : 사용자에게 처음으로 폼(빈 폼 또는 초기 데이터로 채워진 폼)을 보여줌
- 유효한 데이터를 가진 POST : 데이터를 처리함. 주로 리다이렉트 처리됨
- 유효하지 않은 데이터를 가진 POST : 보통은 에러 메시지와 함께 폼이 다시 출력됨
from django.http import HttpResponseRedirectfrom django.shortcuts import render
from .forms import MyForm
def myview(request):
if request.method == "POST":
form = MyForm(request.POST)
if form.is_valid():
# cleaned_date로 관련 로직 처리
return HttpResponseRedirect('/success/')
else:
form = MyForm(initial={'key': 'value'})
return render(request, 'form_template.html', {'form': form})
동일한 로직을 클래스형 뷰로 코딩해보자.
from django.http import HttpResponseRedirectfrom django.shortcuts import render
from django.views.generic import View
from .forms import MyForm
class MyFormView(View):
form_class = MyForm
initial = {'key': 'value'}
template_name = 'form_template.html'
def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
# cleaned_data로 관련 로직 처리
return render(request, self.template_name, {'form': form})
클래스형 뷰에서는 HTTP 의 GET 방식과 POST 방식을 클래스 내의 메소드로 구분하여 처리했기 때문에 구조가 깔끔해진다.
이 코드를 폼 처리용 제네릭 뷰인 FormView를 상속받아 처리하면 코드가 훨씬 간단해진다.
from .forms import MyFrom
from django.views.generic.edit import FormView
class MyFormView(FormView):
form_class = MyForm
template_name = 'form_template.html'
success_url = '/thanks/'
def form_valid(self, form):
#cleaned_data로 관련 로직 처리
return super(MyFormView, self).form_valid(form)
코딩의 내용이 훨씬 단순해졌는데, 다음의 4가지 사항을 유의해 코딩하면 된다.
- form_class : 사용자에게 보여줄 폼을 정의한 forms.py 파일 내의 클래스명
- template_name : 폼을 포함하여 렌더링할 템플릿 파일 이름
- success_url : MyFormView 처리가 정상적으로 완료되었을 때 리다이렉트 시킬 URL
- form_valid() 함수 : 유효한 폼 데이터로 처리할 로직 코딩, super() 함수를 사용하면, success_url 로 지정된 URL로 리다이렉션 처리됨
댓글 없음:
댓글 쓰기