본문 바로가기

프로젝트/파이썬 장고를 이용한 웹페이지 만들기

9. 튜토리얼 따라하기 - 설문조사(4)

이번 시간에는 제네릭 뷰를 사용할 것이다.

마찬가지로 django 문서배프의 오지랖 파이썬 웹 프로그래밍을 참고하고 있다.

 

제네릭 뷰 사용하기

지금까지는 index view를 다음과 같이 HttpResponse, render로 표현해봤다.

 

1. HttpResponse 이용

def index(request):
	latest_question_list = Question.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')
    
    context = {
    	'latest_question_list' : latest_question_list,
    }
    
    return HttpResponse(template.render(context, request))

 

2. render 이용

def index(request):
	latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {
    	'latest_question_list' : latest_question_list,
    }
    return render(request, 'polls/index.html', context)

처음에 사용한 HttpResponse는 코드도 길고 HttpResponse안에 template.render함수까지 넣어줘야하는 것을 볼 수 있다. 즉, 매우 번거롭고 복잡하다. 변경한 render는 HttpResponse에 비해 간결해진 것을 확인할 수 있다. 하지만, render함수보다 더 간단한 제네릭 뷰 시스템이 있다.

 

3. Generic View 이용

from django.views.generic import ListView

class IndexView(ListView):
	model = Question

코드가 정말 간결해진 것을 확인 가능하다.

제네릭 뷰는 장고에서 기본적으로 제공하고 있는 뷰의 형태로, 반복되는 공통 부분을 패턴화하여 사용하기 쉽게 추상화해 둔 시스템이다. 필요에 따라 각 뷰마다 달라지는 값을 넣어주기만 하면 된다. 

 

사실, "첨부터 generic view로 사용하면 되는 것 아닌가?"라는 의구심이 들긴 하지만, Django 튜토리얼에서는 다음과 같이 설명한다.

"왜 코드 셔플인가?"

일반적으로 Django 앱을 작성할 때 일반 뷰가 문제에 적합한 지 여부를 평가할 것이며 코드를 중간에서 다시 리팩토링하지 않고 처음부터 사용하게됩니다. 그러나 이 튜토리얼은 의도적으로 현재까지 핵심 개념에 초점을 맞추기 위해 "어려운 방법"으로 뷰를 작성하는 데 중점을 두었습니다.
계산기를 사용하기 전에 기본 수학을 알아야합니다.

계산기를 사용하기 전에 기본 수학을 알아야 한다는 말...이젠 튜토리얼의 의도가 확실히 이해가 간다.


이젠, 본격적으로 코드를 수정해 보겠다. polls/views.py를 수정한다. 기존에 있던 index, detail, results 뷰는 삭제하자. (vote는 수정하지 말자!!!)

from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
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'

 

위의 코드에선 generic.ListView 와 generic.DetailView를 사용한 것을 확인할 수 있다. 각각은 다음과 같은 기능이 있다.

  • ListView는 조건에 맞는 객체들의 목록을 보여주는 뷰
  • DetailView는 주어진 URL로 바로 Redirect 하는 기능의 뷰

클래스형의 뷰로 바꾸면서 코드가 훨씬 간결해지는 것을 확인할 수 있다.

클래스형의 뷰로 변경하면, urls.py도 수정해야한다. polls/urls.py를 다음과 같이 수정하자.

from django.urls import path
from . import views

app_name = 'polls'

urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),  # ex : /polls/
    path('<int:pk>', views.DetailView.as_view(), name='detail'),  # /polls/5
    path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),  # /polls/5/results/
    path('<int:question_id>/vote/', views.vote, name='vote')   # /polls/5/vote/
]

바뀐 부분은 route 패턴에 들어있는 패턴이름과 view 인자이다. <int:question_id>에서 <int:pk>로 변경했다.

또한, as_view() 함수를 사용했는데, 클래스형 뷰를 사용할 때는 꼭 이 함수를 덧붙여야 한다.

 

django 튜토리얼에서는 테스트도 다루고 있지만, 지금 당장은 테스트를 다루지 않을 생각이다.

추후, 테스트를 해보고 테스트와 관련된 코드들을 올려보겠다.

 

다음에는 설문조사 튜토리얼의 마지막인 관리자 화면 목록을 커스터마이징을 해보겠다.