앞에서 polls 애플리케이션을 설계할 때 3개의 페이지가 필요했습니다.
이 3개의 페이지를 보여주기 위해 필요한 뷰와 템플릿을 코딩해보도록 하겠습니다.
1. 처리 흐름
URL 패턴 뷰 이름 뷰가 처리하는 내용
/polls/ index() index.html 템플릿을 보여줍니다.
/polls/5/ detail() detail.html 템플릿을 보여줍니다.
/polls/5/vote/ vote() detail.html에 있는 폼을 POST 방식으로 처리합니다.
/polls/5/results/ results() results.html 템플릿을 보여줍니다.
/admin/ (장고 기능) Admin 사이트를 보여줍니다. (장고에서 기본적으로 제공)
* URL 패턴에서 5는 예시로, 질문번호가 채워지는 자리입니다.
위 설계 내용을 개발하기 위해 아래 순서대로 코딩하도록 하겠습니다. 코딩 순서는 정해진 것은 없지만, 일반적으로 URLconf, 뷰, 템플릿, 뷰 순서로 코딩합니다.
urls.py 작성 // URLconf 내용을 작성
views.index() 함수 작성 // index.html 템플릿도 같이 작성
view.detail() 함수 작성 // detail.html 템플릿도 같이 작성
views.vote() 함수 작성 // redirection 처리 들어있음
views.results() 함수 작성 // results.html 템플릿도 같이 작성
URLconf 설계 내용에 따르면, Admin 사이트까지 포함하여 5개의 URL과 뷰가 필요합니다. 그 내용을 기계적으로 urls.py 파일에 코딩합니다. 코드는 아래와 같습니다.
$ cd ch3/mysite
$ vi urls.py
from django.conf.urls import patterns, url -------------------------------------------------- 1
from polls import views --------------------------------------------------------------------- 2
urlpatterns = patterns('', ------------------------------------------------------------------ 3
url(r'^polls/$', views.index, name = 'index'),
url(r'^polls/(?P<question_id>\d+)/$', views.detail, name = 'detail'),
url(r'^polls/(?P<question_id)\d+)/vote/$', views.vote, name = 'vote'),
url(r'^polls/(?P<question_id)\d+)/results/$', views.results, name = 'results'), ----- 4
url(r'^admin/', include(admin.site.urls)), ------------------------------------------ 5
)
위의 코드를 라인별로 설명하면 아래와 같습니다.
1. 장고의 내장 함수인 patterns(), url() 두 개의 함수를 import 합니다.
2. URLconf에서 뷰를 지정하므로, 뷰가 정의되어 있는 views 모듈을 임포트합니다.
3. patterns() 함수는 URL/뷰 매핑을 처리하는 함수로, 동일한 형식으로 사용하기 때문에 보이는 그대로 코딩하면 됩니다.
4. url() 함수는 5개의 인자를 가지고 있습니다. 앞의 2개는 필수 인자이고, 뒤에 3개는 선택 인자입니다.
5. 마지막 줄에는 Admin 사이트 관련 URLconf가 정의되어 있습니다. 이처럼 이미 정의된 URLconf를 include() 함수로 가져와서 사용할 수 있습니다.
url() 함수는 장고 라이브러리 django.conf.url.py 파일에 아래처럼 정의되어 있습니다.
url(regex, view, kwargs = None, name = None, prefix = '')
- regex : URL을 정규표현식으로 표현합니다. 정규표현식을 통해 뷰 함수에 넘겨줄 파라미터를 추출할 수 있습니다.
- view : 요청의 URL이 regex 인자에 매칭되면 장고가 뷰 함수를 호출합니다. 뷰 함수에는 HttpRequest와 Regex에서 추출한 항목을 인자로 넘겨줍니다.
- kwargs : regex 인자에서 추출한 파라미터 외에 추가적인 인자를 파이썬 사전 타입의 키워드 인자로 뷰 함수에 넘겨줄 수 있습니다.
- name : 각 URL 별로 이름을 붙여줍니다. 여기서 정해준 이름은 템플릿 파일에서 사용되니 기억해 두기 바랍니다.
- prefix : 뷰 함수에 대한 접두사 문자열입니다. 우리 예제에서는 사용하지 않으니 무시해도 됩니다.
자, 이제 앞에서 코딩한 내용을 살펴보도록 하겠습니다. 각 라인의 의미는 다음과 같습니다.
url(r'^polls/$', views.index, name = 'index'),
만일, 요청의 URL이 /polls/라면 위 라인이 매칭되고, 정규표현식에서 파라미터를 추출하지 않으므로 views.index(request) 처럼 뷰 함수가 호출됩니다. 이 URL 패턴의 이름을 index라고 정했습니다.
url(r'^polls/(?P<question_id>\d+)/$', views.detail, name = 'detail'),
만일, 요청의 URL이 /polls/5/ 라면 위 라인이 매칭되고, 뷰 함수 호출 시 view.detail(request, question_id = '5')처럼 인자가 대입됩니다. 이 URL 패턴의 이름을 detail이라고 정했습니다. 타 라인의 코드의 동작 방식도 이와 같습니다.
url(r'^admin/', include(admin.site.urls)),
만일 요청의 URL이 /admin/이라면 아래 라인이 매칭되고, 장고에서 제공해주는 뷰 함수를 호출합니다. 우리는 아래 라인처럼 include() 함수만으로 Admin 사이트를 그대로 사용할 수 있습니다.
ROOT_URLCONF = 'mysite.urls'
추가적으로, mysite/settings.py 파일에 ROOT_URLCONF 항목이 정의된다는 것을 기억하시기 바랍니다. 장고는 URL 분석 시, 이 항목에 정의된 urls.py 파일을 가장 먼저 분석하시기 바랍니다.
2. URLconf의 코딩 방법
한 가지 더 알아두어야 할 사항은 URLconf를 코딩할 때 앞에서처럼 하나의 urls.py 파일에 작성할 수도 있고, 다음과 같이 mysite/urls.py와 polls/urls.py 2개의 파일에 작성할 수도 있습니다.
mysite/urls.py 코딩 방법
$ cd ch3/mysite
$ vi urls.py
from django.conf.urls import patterns, url, include
from django.contrib import admin
urlpatterns = patterns('',
url(r'^polls/', include('polls.urls', namespace = "polls")),
url(r'^admin/', include(admin.site.urls)),
)
polls/urls.py 코딩 방법
$ cd ch3/polls
$ vi urls.py
from django.conf.urls import patterns, url
from polls import views
urlpatterns = patterns('',
url(r'^polls/$', views.index, name = 'index'),
url(r'^polls/(?P<question_id>\d+)/$', views.detail, name = 'detail'),
url(r'^polls/(?P<question_id)\d+)/vote/$', views.vote, name = 'vote'),
url(r'^polls/(?P<question_id)\d+)/results/$', views.results, name = 'results'),
url(r'^admin/', include(admin.site.urls)), -
)
그렇다면, 위의 두 가지 방식 중 어떤 방식이 좋을까요?
두 번째 방법을 추천합니다. 즉, URLconf 모듈을 계층적으로 구성하는 것이 변경도 쉬워지고 확장도 용이해지기 때문입니다. 만일 URL의 polls를 vote라고 변경한다고 가정했을 때, 1개의 파일로 URLconf를 코딩한 경우는 모든 패턴마다, 즉 위 예제의 경우 4개의 패턴을 수정해야 하지만, 2개의 파일로 URLconf를 코딩한 경우는 사우이 URLconf에서 1개의 패턴만 수정하면 됩니다. 이것이 재사용을 기본 원칙으로 하는 장고의 장점 중 하나입니다.
그리고 mysite/urls.py 파일의 include() 함수를 정의할 때 사용한 namespace 인자는 URL패턴의 이름이 충돌나는 것을 방지하기 위한 것입니다. 우리 예제에서는 애플리케이션이 polls 하나뿐이지만, 보통의 프로젝트에서는 여러 개의 애플리케이션으로 이뤄지는 경우가 대부분입니다. 예를 들어, polls 애플리케이션의 URL패턴 이르과 blog 애플리케이션 URL 패턴 이름이 detail이 되는 경우가 발생할 수 있습니다. 이 둘을 구별하기 위해 include() 함수의 namespace 인자를 사용합니다.