Korean translation of http://www.djangoproject.com/documentation/tutorial3
<-- |
[../Tutorial2] |
[../Tutorial4] |
--> |
당신의 첫번째 장고 프로그램 만들기, part 3
Contents
이 문서는 Django 0.9.1을 다룬다. 구버전 : 0.90 docs
By Adrian Holovaty <holovaty@gmail.com>, Translated by [parkpro77]
튜토리얼 2를 끝마치면 이 튜토리얼을 시작한다. 우리는 웹 투표 프로그램을 계속 만들것이고, 공개화면 (public interface)를 만드는 데 주력할 것이다 -- "보기 (views)"
원리
보기 (view)는 일반적으로 특별한 기능을 제공하는 장고 프로그램에서 웹 페이지의 "형태"이고, 특별한 주형 (template)을 가진다. 예를 들어, 웹블로그 프로그램에서, 당신은 다음 보기들을 가질지도 모른다:
- Blog homepage -- 최근 소수의 항목들 (entries)을 보여준다.
- Entry "detail" page -- 하나의 항목 (single entry)을 위한 고유주소(permalink).
- Year-based archive page -- 주어진 해에 항목들과 함께 모든 달을 보여준다.
- Day-based archive page -- 주어진 날에 모든 항목들을 보여준다.
- Comment action -- 주어진 항목에 알리는 주석들 (posting comments)을 처리한다.
투표 프로그램에서, 우리는 다음 네가지 보기를 가질 것이다:
- Poll "archive" page -- 최근 소수의 투표들 (polls)을 보여준다.
- Poll "detail" page -- 결과는 없지만 투표하는 형태를 가진 투표 질문 (poll question)을 보여준다.
- Poll "results" page -- 특별한 투표에 대한 결과를 보여준다.
- Vote action -- 특별한 투표에서 특별한 선택을 하기 위한 투표를 처리한다.
장고에서, 각 보기는 간단한 파이썬 기능에 의해 표현되어졌다.
URL들을 만들기
보기들을 쓰는 첫번째 단계는 당신의 URL 구조를 만드는 것이다. URL 구조는 URLconf로 불려지는 파이썬 모듈을 만드는 것이다. URLconfs 는 장고가 어떻게 주어진 파이썬 코드와 주어진 URL을 결합시키는가 하는 것이다.
사용자가 장고 페이지를 요청했을 때, 파이썬의 점으로 된 문법 (Python dotted syntax)에 문자열을 포함하는 ROOT_URLCONF 구성을 시스템에서 본다. 장고는 모듈을 적재하고, 다음 형식에서 튜플들의 연속인 urlpatterns 라 불려지는 다양한 모듈 단계를 찾는다:
(regular expression, Python callback function [, optional dictionary])
장고는 첫 규칙적인 표현을 시작하고, 그것이 적합한 하나를 찾을 때까지, 각 규칙적인 표현에 대한 요청된 URL을 비교하는 목록 아래 그것의 방법을 만든다.
그것이 서로 맞는것을 찾을 때, 장고는 첫 인수로서 HTTPRequest 객체와 함께 파이썬 회수 (callback)기능을 호출하고, 키워드 인수로서 규칙적인 표현으로부터 어떤 "입력된 (captued)"값을 호출하고, 선택적으로, 디렉토리 (튜플에서 선택적인 세번째 항목)로부터 임의의 키워드 인수들을 호출한다.
HTTPRequest 객체에 대해 더 알고 싶다면, request and response documentation을 보아라. URLconfs에 대해 알고 싶으면, URLconf documentation을 보면 된다.
튜토리얼1의 시작에서 python manage.py startproject myproject 를 실행했을 때, 그것은 myproject/urls.py 에 초기설정으로 URLconf를 만들었다. 또한, 그 파일을 지목하기 위해 ROOT_URLCONF 를 구성했다:
ROOT_URLCONF = 'myproject.urls'
이제는 예제. myproject/urls.py 를 이와 같이 편집하라:
1 from django.conf.urls.defaults import *
2
3 urlpatterns = patterns('',
4 (r'^polls/$', 'myproject.polls.views.index'),
5 (r'^polls/(\d+)/$', 'myproject.polls.views.detail'),
6 (r'^polls/(\d+)/results/$', 'myproject.polls.views.results'),
7 (r'^polls/(\d+)/vote/$', 'myproject.polls.views.vote'),
8 )
이것은 재검토 해볼만하다. 누군가가 당신의 웹 싸이트 페이지를 요청할 때 -- "/polls/23/"을 말하는 --, 장고는 이 파이썬 모듈을 적재할 것이다. 왜냐하면, 그것은 ROOT_URLCONF 구성에 의해 지목되어졌기 때문이다. 그것은 다양하게 이름지어진 urlpatterns 를 찾고, 순서에 따라 규칙적인 표현은 통과한다. 그것이 규칙적인 표현을 찾을 때, --r'^polls/(\d+)/$'-- 과 들어 맞게 되고, 결합되어진 파이썬 package/module 을 적재한다: myproject.polls.views.detail. 그것은 myproject/polls/views.py 안에 detail() 기능과 일치한다. 결국엔, 이와 같이 detail() 기능을 호출한다:
detail(request=<HttpRequest object>, poll_id='23')
poll_id='23' 은 (\d+)으로부터 나온다. 형태에 의해 들어맞는 본문인 "입력 (captures)" 형태 주위에 괄호를 사용하고, 보기 기능에서 인수로서 그것을 보내라.
URL 형태들은 규칙적인 표현들이기 때문에, 그것들과 함께 무엇을 할 수 있는지에 대한 제한이 없다. 그리고, .php 같이 URL cruft 를 추가하는 것이 필요하지 않다 -- 당신이 유머 감각을 가지고 있다면, 그런 경우에 이와 같은 것을 할 수 있다:
(r'^polls/latest\.php$', 'myproject.polls.views.index'),
하지만, 그렇게 하지 말아라. 그것은 어리석은 짓이다.
이런 규칙적인 표현들은 GET and POST 변수들이나 도메인 이름을 조사하지 않는다. 예를 들면, http://www.example.com/myapp/ 요청에서 URLconf는 /myapp/를 찾을 것이다. http://www.example.com/myapp/?page=3 요청 또한 /myapp/를 찾을 것이다.
규칙적인 표현들에 대한 도움이 필요하다면, Wikipedia's entry와 Python documentation을 보아라. Jeffrey Friedl 의 O'Reilly의 책 "Mastering Regular Expressions" 또한 환상적이다.
마지막으로, 수행 기록 (performance note): 이런 규칙적인 표현들은 URLconf 모듈이 적재되었을 첫번째로 컴파일되어졌다. 그것들은 굉장히 빠르다.
당신의 첫번째 보기 작성하기
우리는 아직 어떤 보기 (views)도 만들지 않았었다 -- 단지 URLconf만 가지고 있다. 장고가 다음과 같은 URLconf인지 확인해 보자.
장고 개발 웹 서버를 가동하자:
python manage.py runserver
이제 "http://localhost:8000/polls/" 로 가자. 다음 메세지와 같은 유쾌하게 색깔있는 오류 (pleasantly-colored error)를 얻게 될 것이다:
ViewDoesNotExist at /polls/ Tried index in module myproject.polls.views. Error was: 'module' object has no attribute 'index'
이 오류는 myproject/polls/views.py 모듈에서 index() 기능을 작성하지 않았기 때문에 나타났다.
"/polls/23/"과 "/polls/23/results/", "/polls/23/vote/"를 시험해 보자. 에러 메세지는 장고가 시도했던 것을 보여준다 (아직 어떤 보기도 작성하지 않았기 때문에 검색은 실패했다.).
첫번째 보기를 작성하는 시간. myproject/polls/views 파일을 열고, 파일 안에 다음 파이썬 코드를 적자:
이것은 사용하기에 가장 간단한 보기이다. "/polls/"로 가면, 당신이 작성한 문서를 볼 것이다.
이제 다음 보기를 추가하자. 그것은 인수를 가지고 있기 때문에 약간 다르다 (which, remember, is passed in from whatever was captured by the regular expression in the URLconf):
당신의 브라우저에서 "/polls/34/"로 접속해 보아라. URL에서 당신이 작성한 ID가 보여질 것이다.
실질적인 작업을 수행하는 보기 작성하기
각각의 보기는 두 가지 중에 하나를 수행하는 책임이 있다: 요청된 페이지 내용을 포함하는 HttpResponse 객체를 되돌리거나, Http404 같은 예외를 일으킨다. 안정 (rest)은 당신에게 달려 있다.
당신의 보기는 데이타베이스로부터 기록들을 읽을 수 있거나 없다. 그것은 장고 -- 제3자 파이썬 주형 시스템이나 -- 와 같은 주형 시스템을 사용할 수 있거나 없다는 것이다. 그것은 PDF 파일과 XML 출력이 발생할 수 있고, 당신이 원하는 어떤것이나 그 어떤 파이썬 라이브러리들을 사용하는데에 쉴새없이 XIP 파일을 만들 수 있다.
장고가 원하는 모든 것은 HttpResponse 아니면 예외이다.
그것은 편리하기 때문에, 우리가 튜토리얼1에서 작성했던 장고의 데이타베이스 API를 사용하자. 여기에 콤마에 의해 분리되어지고, 공적인 시간을 따르는 시스템에서 최근 5개 투표 질문을 보여주는 index() 보기의 시도가 있다:
여기엔 문제가 있다: 페이지의 디자인은 보기에서 어렵게 코드되어져 (hard-coded)있다. 페이지 보는 방법을 바꾸길 원한다면, 당신은 파이썬 코드를 편집해야 할 것이다. 그래서 파이썬으로부터 디자인을 분리하기 위해 장고의 주형 시스템을 사용하자:
1 from django.core.template import Context, loader
2 from django.models.polls import polls
3 from django.utils.httpwrappers import HttpResponse
4
5 def index(request):
6 latest_poll_list = polls.get_list(order_by=['-pub_date'], limit=5)
7 t = loader.get_template('polls/index')
8 c = Context({
9 'latest_poll_list': latest_poll_list,
10 })
11 return HttpResponse(t.render(c))
코드는 "polls/index" 주형을 적재하고, 그것의 내용 (Context)을 통과한다. 내용은 파이썬 객체들의 다양한 이름들의 주형을 나타내는 사전이다.
페이지를 재적재하라. 이제 에러를 보게 될 것이다:
TemplateDoesNotExist: Your TEMPLATE_DIRS settings is empty. Change it to point to at least one template directory.
아, 아직 주형이 없다. 첫번째로, 장고가 접근할 수 있는 내용들의 파일시스템 어딘가에 사전을 만들자. (장고는 당신 서버가 돌아갈 때, 어떤 사용자로서 실행된다.) 그렇지만, 당신의 문서 루트 아래에는 그것을 두지 말아라. 아마도 당신은 보안의 이유로, 공적으로 그것을 만들지 않을 것이다.
그 다음에 주형을 찾을 수 있는 장고에게 알리기 위해 settings.py 에서 TEMPLATE_DIRS 를 편집하라 -- 당신은 튜토리얼2의 "Customize the admin look and feel"에서 했었다.
당신이 그것을 했을때, 주형 디렉토리에서 polls 디렉토리를 만들자. 그것 안에, index.html이라 불리는 파일을 만들자. 장고는 주형들이 ".html" 확장을 가지는 것이 필요하다. 파일 시스템에 위의 지도로부터 "[template_directory]/polls/index.html" 에서의 loader.get_template('polls/index') 를 주목하라.
주형에 다음 코드를 작성하라:
웹 브라우저에 페이지를 적재하면, 당신은 튜토리얼1에서 만든 "What's up" 투표를 포함하는 목록 (bulleted-list )을 볼 것이다.
단축키: render_to_response()
그것은 템플릿을 적재하고, 내용을 채우고, 넘겨진 (rendered) 템플릿의 결과와 함께 HttpResponse 객체를 되돌리는 매우 평범한 표현이다. 장고는 단축키를 제공한다. 여기에 완전한 index() 가 있으니, 재작성하자:
우리는 더 이상 loader나 Context, HttpResponse 가 필요하지 않다.
render_to_response() 기능은 첫번째 인수와 그것의 선택적인 두번째 인수로서의 사전으로 주형 이름을 얻는다. 그것은 주어진 내용과 함께 넘겨졌던 주형의 HttpResponse 객체를 되돌린다.
404 예외 일으키기
이제, 투표 세부 보기 (poll detail view)를 살펴보자 -- 주어진 투표에 대해 질문을 보여주는 페이지. 여기에 보기가 있다:
새로운 발상: 요청된 ID를 가진 투표가 존재하지 않으면, 보기는 django.core.exceptions.Http404 예외를 일으킨다.
단축키: get_object_or_404()
이것은 객체가 존재하지 않는다면 Http404를 일으키고, get_object() 를 사용하는 매우 평범한 표현이다. 장고는 단축키를 제공한다. 여기 detail() 보기가 있으니 재작성하라:
get_object_or_404() 기능은 그것의 첫번째 인수 그리고 모듈의 get_object() 기능을 통과하는 키워드 인수의 임의의 수로서의 장고 모델 모듈을 얻는다. 그것은 객체가 존재하지 않을 때, Http404 를 일으킨다.
{{| 원리
왜 우리는 높은 수준에서 *DoesNotExist 예외를 자동적으로 잡아주는 것 대신에 get_object_or_404()기능을 사용하거나 Http404 를 일으키는 모델 API를 가지고 있는가?
왜냐하면 보기 단계 (layer)에서 모델 단계를 연결할 것이기 때문이다. 장고의 주요한 디자인 목표중에 하나는 자유로운 연결 (loose coupling)을 유지하는 것이다. |}}
get_object_or_404() 처럼 일하는 get_list_or_404() 기능이 있다 -- get_object() 대신에 get_list() 를 사용하는 것을 제외하고. 리스트가 비어 있다면 그것은 Http404를 일으킨다.
404(찾을 수 없는 페이지) 보기를 작성하기
보기 내로부터 Http404를 일으켰을 때, 404 에러들을 처리하는데 장고는 헌신적인 특별한 보기를 적재할 것이다. 그것은 파이썬에서 점으로 된 문법 (Python dotted syntax) -- 표준적인 URLconf 호출을 사용하는 같은 형태 -- 에서 문자열인 다양한 handler404를 찾기 위해 그것을 찾는다. 404 보기는 특별하게 언급하고 있다. 그것은 단지 표준적인 보기이다.
당신은 404 보기들을 작성하는 것에 고민하지 않아도 될 것이다. 초기설정에 의해, URLconf는 위쪽에 다음 라인을 가지고 있다:
1 from django.conf.urls.defaults import *
그것은 현재 모듈에서 handler404 구성을 책임지고 있다. django/conf/urls/defaults.py 에서 당신이 볼 수 있는 것처럼, handler404는 초기설정에 의해 'django.views.defaults.page_not_found' 을 구성했다.
404 보기들에 대해 주의하기 위한 중요한 3가지:
- 장고가 URLconf에서 모든 규칙적인 표현을 검사한 후에도 알맞은 것을 찾지 못했을 경우 404 보기는 불려진다.
- 자신의 404 보기가 정의되어지지 않았다면 -- 그리고 간단하게 추천되어진 초기설정을 사용한다면 -- 당신은 여전히 하나의 책임이 있다: 당신의 주형 디렉토리의 루트에서 404.html 주형을 만드는 것. 404 보기의 초기설정은 모든 404 에러들을 위한 주형을 사용할 것이다.
- DEBUG가 TRUE로 구성되었다면 (당신의 settings 모듈에서) 그 때 404 보기는 결코 사용되어질 수 없을 것이고, 역추적 (traceback)이 대신 보여질 것이다.
500(서버 에러) 보기 작성하기
유사하게, URLconf들은 서버 에러의 경우에 불려지는 보기들을 지적하는 handler500을 설명할 수 있을지도 모른다. 서버 에러는 보기 코드에서 실행시간 오류 (runtime errors)들을 가지고 있을 때 일어난다.
주형 시스템 사용하기
polls.detail 보기로 돌아가자. 다양한 poll의 내용들이 주어졌고, 여기에는 주형이 무엇처럼 보이는지 알 수 있다:
<h1>{{ poll.question }}</h1> <ul> {% for choice in poll.get_choice_list %} <li>{{ choice.choice }}</li> {% endfor %} </ul>
주형 시스템은 다양한 속성들에 접근하기 위해서 점-조회 체계 (dot-lookup syntax)를 사용한다. 의 예에서, 처음 장고는 객체 poll에 사전 조회를 한다. 그것이 실패한다면, 속성 조회 -- 이런 경우에 행해지는 -- 를 시도한다. 속성 조회가 실패했다면, poll 객체에 question() 메쏘드를 호출하려고 시도할 것이다.
메쏘드-호출은 {% for %} 루프에서 일어난다: poll.get_choice_list 는 Choice 객체들의 목록을 되돌리고, {% for %} 태그를 경유한 반복에 적당한 파이썬 코드 poll.get_choice_list() 로 해석되어졌다.
주형들이 어떻게 작동하는지 자세히 알고 싶으면 template guide를 보아라.
URLconfs 간단히 하기
보기들과 주형 시스템을 가지고 놀기 위해 얼마간의 시간을 소비하라. URLconf를 편집할 때, 그것 안에 반복이 어느 정도 있다는 것을 인지해야 할지도 모른다:
다시 말하면, myproject.polls.views 는 모든 호출안에 있다.
이것은 일반적인 경우이기 때문에, URLconf 구조물 (framework)은 일반적인 접두사 (prefix)들을 위한 단축키를 제공한다. 당신은 일반적인 접두사들을 제외시킬 수 있고, 이와 같이 patterns()의 첫번째 인수로서 그것들을 추가할 수 있다:
이것은 전에 형태에 대해서 기능적으로 동일하다. 단지 약간 깔끔하게 하는 것이다.
URLconfs를 분리하기
우리가 그것을 하는 동안, 장고 프로젝트 구성으로부터 투표 프로그램 URLs을 분리하는 데는 시간이 걸릴 것이다. 장고 프로그램은 접속할 수 있게 되어있다 -- 즉, 각 개개의 프로그램은 약간의 불평과 함께 다른 장고 설치로 이동할 수 있을 것이다.
투표 프로그램은 python manage.py startapp 로 만들어졌던 절대적인 디렉토리 구조 때문에 이 점에서 제법 분리되어졌지만, 그것 중에 한 부분은 장고 구성 (settings)에서 결합되어졌다: URLconf.
우리는 myproject/urls.py에서 URLs를 편집했었지만, 프로그램의 URL 디자인은 장고 설치에서가 아닌 프로그램에서 특별하다 -- 그래서, 프로그램 디렉토리 내로 URLs를 옮기자.
myproject/polls/urls.py 로 myproject/urls.py 파일을 복사하자. 그 때, 특별한 투표 URLS를 제거하고, include()를 삽입하기 위해 myproject/urls.py 를 바꿔라.
(r'^polls/', include('myproject.polls.urls')),
간단하게, include()는 다른 URLconf를 참조한다. $(문자열의 끝은 문자와 맞는다)를 가지고 있지는 않지만, 슬래쉬 (trailing slash)는 가지고 있는 규칙적인 표현에 주목하라. 장고가 include()를 만날때마다, 그것은 어떤 시점까지 맞았던 URL의 어떤 부분을 자르고, 그 이상의 과정을 위해 포함된 URLconf의 남아있는 문자열을 보낸다.
만일 사용자가 "/polls/34/"으로 간다면 무슨 일이 일어나는지 보아라.
- 장고는 '^polls/'에 맞는 것을 찾을 것이다.
- 그것은 알맞은 본문("polls/") 을 찾을 것이고, 그 이상의 과정을 위해 'myproject.polls.urls' urlconf로 남아있는 본문 -- "34/" -- 를 보낼 것이다.
이제 우리는 그것을 분리했고, 각 라인으로부터 읽은 "polls/"를 제거하기 위해 'myproject.polls.urls'의 urlconf를 분리하는 것이 필요하다:
include() 배후의 생각과 URLconf 분리는 URLs을 바로 사용할 수 (plug-and-play)있도록 쉽게 만드는 것이다. 이제 polls는 자신의 URLconf 안에 있고, "/polls/"나 "/polls/", "/content/polls/", 다른 URL 루트 아래 있을 것이고, 투표는 여전히 작동하고 있을 것이다.
모든 투표 프로그램의 근심은 절대적인 URLs이 아니라 상대적인 URLs이다.
당신이 작성한 보기들이 익숙해지면, 간단한 형태 처리와 일반적인 보기들을 배우기 위해 [../Tutorial4] 를 읽어라.