Django 07편 - polls app 구현하기 4편
포스트
취소

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에서 변수를 재지정해주는게 더 쉽다.
  • 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 라이센스를 따릅니다.