당신은 멋쟁이, 우리는 장고쟁이~

0%

Writing your first Django app, part4 - 2편

Generic 뷰 사용하기


적은 코드가 낫다


Part3 에서 detail() 과 results() 뷰들은 매우 짧지만, 중복이 됩니다.

index() 뷰도 비슷하고, 투표 리스트를 출력합니다.


이 뷰들은 공통적인 기본 웹개발 방법을 대표합니다.


  1. URL 에서 전달된 파라미터에 따라서 데이터를 데이터베이스에서 가져오고
  2. 템플릿을 읽고 처리된 템플릿을 반환합니다

이것은 매우 공통된 부분이기 때문에, 이것을 쉽게 다룰수 있는 generic view 시스템을 Django 가 제공합니다.



왜 GenericView 인가?



Generic view 는 웹개발에서 공통된 패턴들에 대해서
더이상 파이썬 코드들을 쓸 필요가 없는 지점까지 추상화 합니다.


튜토리얼에서 작업하고 있었던 polls 앱을 generic view 를 사용하도록 전환 해 봅시다.

몇가지 코드를 지우고도 사용할수 있게 됩니다! 전환을 위해서 다음 스텝들을 거쳐 갑니다.


  1. URLConf 바꾸기
  2. 불필요하고 오래된 코드 삭제하기
  3. Django 의 genericview 를 기반으로 하는 새로운 코드 쓰기

왜 코드를 다시 작업하는가?

보통 Django 앱을 작성할때에는,

generic view 를 사용하는것이 문제 해결에 도움이 되는지에 대해 먼저 파악 합니다.

코드를 중간에 리펙토링 하지 않고, 처음부터 generic view 를 사용합니다.

튜토리얼에서는, 단지 의도적으로 주요 컨셉에 집중하기 위해서

어려운 방식으로 뷰를 작성 했었던것 뿐입니다.



Generic view 로 전환


Views 수정하기


index, detail 그리고 results 뷰들의 오래된 코드들을 삭제하고, django 의 generic view 를 사용해 봅니다. generic view 를 사용하기 위해서, polls/views.py 파일을 열고, 아래와 같이 코드를 바꾸어 줍니다.


polls/views.py 파일을 열고, 아래 뷰들을 수정해 줍니다.

index()

detail()

results()

vote() 는 수정해 주지 않습니다.


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
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'


def vote(request, question_id):
... # same as above, no changes needed.


여기서 우리는 두개의 generic view 를 사용합니다. ListView 와 DetailView 입니다.


ListView 는 “모든 객체의 리스트를 출력하기”

DetailView 는 “디테일 페이지 출력하기”

이 두가지 아이디어를 요약 하여, genericview 가 만들어 졌습니다.



  • 각 generic view 들은 어떤 모델을 사용해서 작동해야 할지 알아야 합니다. 이것은 model 속성들 사용에 의해서 주어집니다.
  • DetailView 는 URL 에서 켑쳐된 Primary Key 를 기대하고 있기 때문에, question_id 를 pk 로 바꿔줍니다.

DetailView


기본값으로 DetailView<appname>/<model name>_detail.html템플릿 형태를 사용합니다. 튜토리얼 예시에서는 “polls/question_detail.html” 템플릿을 사용할것 입니다.




하지만, 이번 튜토리얼에서는 template_name = “polls/detail.html” 을 둠으로써,

기존에 만든 템플릿을 사용하게 하였습니다.

template_name 속성은,

기본으로 정해진 템플릿명 대신에 django에게 특정 템플릿 이름을 사용하게 합니다.




template_name 속성을 results 리스트 뷰에도 명시하여,
기존에 사용했던 results view 와 detail view 가 화면에 출력 될때, 다르게 render 되게 만듭니다.
이렇게 되면 두 뷰가 같은 DetailView 라고 해도, 다르게 표시가 됩니다.



ListView





비슷한 맥락으로, ListView 는 기본 템플릿으로 <app name>/<model name>_list.html을 사용합니다.

하지만, 우리는 tempalte_name = ‘polls/index.html’ 템플릿으로 명시를 해줌으로써,
ListView 가 기존에 있던 ‘polls/index.html’ 템플릿을 사용하도록 설정해줍니다.



이전 튜토리얼 과정에서, 템플릿들은 question 과 lastest_question_list 컨텍스트 변수들을 가지고 있는 컨텍스트들을 전달 받았었습니다.
DetailView 는 question 변수가 자동으로 주어집니다. 이것은 모델명을 기반으로 가져오는것이라,
자동으로 DetailView 가 적절한 컨텍스트 변수명을 판단하여 가져옵니다.




ListView 에 context 변수명 속성을 명시해 줍니다

context_object_name = latest_question_list

ListView는 기본적으로 자동으로 생성하는 컨텍스트 변수명은 question_list 입니다. 이 context 변수명을 명시를 해주기 위해서,

context_object_name 속성을 지정해 줍니다.




context_object_name 을 지정해주고 싶지 않다면, 그냥 템플릿에서 context 변수명들을 바꾸어 주면 됩니다.



URL 세팅해주기



views.py 에 있는 뷰들이 generic view 들인 클래스 뷰들로 바뀌었습니다.

vote 를 제외한 index, detail 그리고 results 뷰들이 바뀌었고. 이것들이 url 에서 호출되도록 변경해주어야 합니다.



polls/urls.py 파일을 열어서, index, detail 그리고 results 뷰에 대한 URL설정을 고쳐줍니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
from django.urls import path

from . import views

app_name = 'polls'

urlpatterns = [
path("", views.IndexView.as_view(), name='index'),
path('specifics/<int:pk>/', views.DetailView.as_view(), name='detail'),
# <int:question_id> 를 <int:pk> 로 바꾸어줌
path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
# <int:question_id> 를 <int:pk> 로 바꾸어줌
path('<int:question_id>/vote/', views.vote, name='vote'),
]




IndexView, DetailView 그리고 ResultsView 는

클래스 기반의 generic view 입니다.

이 뷰들을 URL에서 호출하려면,

view 뒤에 as_view() 함수를 붙여줘야 잘 작동합니다.

그리고, int:question_idint:pk 로 바꾸어줘야 작동합니다.

왜냐하면, DetailView 는 pk 를 인자로 받기 때문입니다.





서버를 시작하고, 한번 시험해 봅니다. IndexView 호출



DetailView 호출


ResultsView 호출



마치며..



사전 지식 없이 튜토리얼만 보고 공부 시작했다가 낭패 봤습니다.

겨우겨우 찾아서, 클래스 기반의 뷰들을 작성 해보았지만.. 알아내기 힘들었습니다.


폼과 generic view 와 친숙해 졌으면, part5 로 넘어갑니다.