Django 07편 - polls app 구현하기 4편
제너릭 뷰로 리팩토링 해보자!
- 불필요한 레거시 뷰 중 일부를 삭제한다.
- Django의 제너릭 뷰를 기반으로 새로운 뷰를 도입해본다.
- URLconf를 수정한다.
views.py 수정
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
import logging from .models import Question, Choice from django.shortcuts import render, get_object_or_404 from django.http import HttpResponseRedirect from django.urls import reverse from django.views import generic logger = logging.getLogger('debug') # Create your views here. # 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) 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] # def detail(request, question_id): # question = get_object_or_404(Question, pk=question_id) # return render(request, 'polls/detail.html', {'question': question}) class DetailView(generic.DetailView): model = Question template_name = 'polls/detail.html' # def results(request, question_id): # question = get_object_or_404(Question, pk=question_id) # return render(request, 'polls/results.html', {'question': question}) class ResultsView(generic.DetailView): model = Question template_name = 'polls/results.html' def vote(request, question_id): question = get_object_or_404(Question, pk=question_id) try: selected_choice = question.choice_set.get(pk=request.POST['choice']) except (KeyError, Choice.DoesNotExist): # Redisplay the question voting form. return render(request, 'polls/detail.html', { 'question': question, 'error_message': "You didn't select a choice.", }) else: selected_choice.votes += 1 selected_choice.save() # Always return an HttpResponseRedirect after successfully dealing # with POST data. This prevents data from being posted twice if a # user hits the Back button. return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
- DetailView
- DetailView 제너릭 뷰는 기본값으로 <app name>/<model name>_detail.html 템플릿을 사용한다.
- template_name 속성은 Django에게 자동 생성 된 기본 템플릿 이름 대신에 특정 템플릿 이름을 사용하도록 알려주기 위해 사용된다.
- 결과 뷰의 DetailView에 template_name을 지정한다.(결과 뷰와 상세 뷰가 렌더링 될 때 이들이 둘다 동일한 DetailView를 사용하고 있더라도 서로 다른 모습을 갖도록한다.)
- ListView
- DetailView의 경우 question 변수가 자동으로 제공되며, Django 모델 (Question)을 사용하고 있기 때문에 Django는 컨텍스트 변수에 대한 적절한 이름을 결정한다.
- 하지만 이 코드에서 ListView는 자동으로 제공하는 컨텍스트 변수가 question_list 이다.
- context_object_name 속성을 제공하여 대신 latest_question_list를 사용하도록 지정할 수 있다.
- 템플릿에서 맞출 수도 있지만 django에서 변수를 재지정해주는게 더 쉽다.
- DetailView
urls.py 수정
1 2 3 4 5 6 7 8 9 10
from django.urls import path from apps.polls import views as polls_views app_name = 'polls' urlpatterns = [ path('', polls_views.IndexView.as_view(), name='index'), path('<int:pk>/', polls_views.DetailView.as_view(), name='detail'), path('<int:pk>/results/', polls_views.ResultsView.as_view(), name='results'), path('<int:question_id>/vote/', polls_views.vote, name='vote'), ]
두 번째와 세 번째 패턴의 경로 문자열에서 일치하는 패턴들의 이름이 <question_id> 에서 <pk> 로 변경되었다.
더 알아보기
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.