나의 첫 Django 앱 만들기 - part 4 - 2

제너릭 뷰 사용하기: Less code is better

지난 강좌인 나의 첫 Django 앱 만들기 - part 3 - 1에서 만든 detail()results() 뷰는 아주 심플하고 두 뷰는 비슷한 구조를 가졌습니다. Question 인스턴스의 리스트를 보여주는 index() 뷰도 비슷하게 생겼습니다.

이 뷰들은 URL안의 파라메터를 보고 데이터베이스에서 필요한 데이터를 가져와 템플릿을 로딩하여 보여주는 웹 개발에서 일반적으로 사용되는 기본적인 형식입니다. 장고는 개발자들을 위해 이러한 일반적인 코드의 반복을 없애주는 숏컷을 제공하고 있습니다. 그것이 제너릭 뷰 시스템입니다.

제너릭 뷰는 파이썬 코드를 쓰지 않고도 앱을 만들 수 있도록 일반적인 패턴을 제거하여 줍니다.

우리의 투표앱 안에서 제너릭 뷰 시스템을 사용하여 코드의 양을 줄여보도록 하죠. 절차는 다음과 같이 아주 간단합니다.

  1. URLconf를 수정합니다.
  2. 필요없는 뷰 함수를 삭제합니다.
  3. 장고의 제너릭 뷰를 사용합니다.

자세한 절차는 밑에서 다루도록 하겠습니다.

왜 이제와서 코드를 변경할까요?

일반적으로는 장고 앱을 만들기 전에 제너릭 뷰를 사용할 수 있는지를 판단하고 프로젝트를 진행중 보다는 시작할 때부터 사용을 합니다. 그러나 이 강좌에서는 기본 컨셉트를 공부하기 위해서 의도적으로 어려운 방법을 선택했습니다.

계산기의 사용법을 배우기 전에 산수나 수학을 배우는 것과 같다고 생각하시면 됩니다.

URLconf 수정

먼저 polls/urls.py URLconf를 다음과 같이 수정하여 주십시오.

polls/urls.py
from django.conf.urls import url

from . import views

app_name = 'polls'
urlpatterns = [
    url(r'^$', views.IndexView.as_view(), name='index'),
    url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
    url(r'^(?P<pk>[0-9]+)/results/$', views.ResultsView.as_view(), name='results'),
    url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]

3번째, 4번째 url()의 regex 매칭패턴의 이름이 <question_id>에서 <pk>로 바뀐것을 확인하여 주십시오.

뷰 수정

다음은 전에 만든 index, detail, results 뷰를 지우고, Django의 제너릭 뷰를 대치하여 사용하겠습니다. polls/views.py 파일을 다음과 같이 수정하여 주십시오.

polls/views.py
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.views import generic

from .models import Choice, Question


class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        """Return the last five published questions."""
        return Question.objects.order_by('-pub_date')[:5]


class DetailView(generic.DetailView):
    model = Question
    template_name = 'polls/detail.html'


class ResultsView(generic.DetailView):
    model = Question
    template_name = 'polls/results.html'


def vote(request, question_id):
    ... # 이 뷰는 수정할 필요가 없습니다.

위의 코드는 ListView 와 DetailView. 2개의 제너릭 뷰를 사용하고 있습니다. ListView는 오브젝트 리스트를 보여주고, DetailView는 특정 오브젝트의 디테일을 보여주는 역할을 합니다.

  • 각 제너릭 뷰는 어떤 모델을 사용할 것인지 알아야합니다. 이 모델은 "model" 속성으로 전달됩니다.
  • DetailView 제너릭 뷰는 URL에서 캡처된 기본키인 'pk'를 전달 받아야 합니다. 그래서 question_id  를 pk 로 수정한 것입니다.

DetailView 제너릭 뷰는 기본적으로 <app name>/<model name>_detail.html 이름의 템플릿을 사용합니다. 위의 예제의 경우는 template_name 속성을 사용하여 지정하였지만, 만약 지정을 하지 않는다면 장고는 자동으로 "polls/question_detail.html"를 사용하게 됩니다. template_name 속성을 사용하면 자동으로 생성되는 템플릿 이름 대신으로 원하는 이름을 지정할 수가 있습니다. 위의 예제에서는 results 리스트 뷰의 template_name을 정의 하였습니다. 이것은 results 뷰와 detail 뷰는 둘다 DetailView 의 서브클래스이지만, 다른 모양을 가고 있기 때문입니다.

ListView 제너릭 뷰 또한 <app name>/<model name>_list.html;  형식의 디폴트 이름을 사용합니다. 위의 예제에서는 기존에 만든 템플릿인 "polls/index.html"을 ListView 의 템플릿으로 사용하였습니다.

이전 강좌에서는 question 과 latest_question_list 변수를 포함한 context를 템플릿에 전달하였습니다. 하지만 DetailView 를 사용할 때에는 장고 모델(Question)을 사용하기 때문에 question 변수가 자동으로 템플릿에 전달 됩니다. 장고가 적당한 context  변수의 이름을 정해주는 것입니다. 그러나 ListView의 경우에는 자동으로 생성되는 변수의 이름은 question_list입니다. 자동으로 생성되는 이름을 변경하고 싶으시면, 위의 예제에서 latest_question_list 를 사용한 것처럼 context_object_name 속성을 사용하면 됩니다.

서버를 실행하시고 제너릭 뷰로 만든 투표 앱을 사용해 보십시오.

제너릭 뷰에 대한 자세한 정보는 generic views documentation를 참고 하여 주십시오.

제너릭 뷰의 사용이 익숙해지셨다면 다음 강좌인 part 5 of this tutorial 에서 앱 테스팅에 대해서 알아 보겠습니다.


blog comments powered by Disqus