Django 공식 문서 v3.0 Tutorial
https://docs.djangoproject.com/en/3.0/intro/tutorial03/
https://github.com/JisunParkRea/django-tutorial-mypractice
Overview
Tutorial의 poll application에선 다음 4개의 view를 만든다.
View 만들기(연습)
polls/views.py에 다음 코드를 붙여써보자
def detail(request, question_id):
return HttpResponse("You're looking at question %s." % question_id)
def results(request, question_id):
response = "You're looking at the results of question %s."
return HttpResponse(response % question_id)
def vote(request, question_id):
return HttpResponse("You're voting on question %s." % question_id)
새로 만든 view들을 polls.urls 모듈에 연결하자. 다음의 path() calls를 더해보자
from django.urls import path
from . import views
urlpatterns = [
# ex: /polls/
path('', views.index, name='index'),
# ex: /polls/5/
path('/', views.detail, name='detail'),
# ex: /polls/5/results/
path('/results/', views.results, name='results'),
# ex: /polls/5/vote/
path('/vote/', views.vote, name='vote'),
]
결과:
detail(request=<HttpRequest object>, question_id=5) 가 호출된 것
View 만들기(실전)
각각의 view가 하는 일은 크게 2개
- HttpResponse object를 return
- Http404과 같은 exception 처리
index() view를 최신의 5개 poll questions를 콤마로 구분하여 publication date에 따라 display하게 하자
polls/views.py를 다음 코드로 고쳐보자
from django.http import HttpResponse
from .models import Question # 이 부분도 추가
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
output = ', '.join([q.question_text for q in latest_question_list])
return HttpResponse(output)
# Leave the rest of the views (detail, results, vote) unchanged
그리고 페이지의 디자인을 변화시키기 위해선
Django의 Template system을 이용하자.
우선, polls 디렉토리에 templates 디렉토리를 만들자.
그리고 방금 만든 templates 디렉토리 안에 또 다른 polls란 디렉토리를 만들자.
그리고 방금 만든 polls 디렉토리 안에 index.html 파일을 만들자.
즉, polls/templates/polls/index.html 가 되어야 한다.
Django 안에선 이 template를 polls/index.html 로 사용해도 된다.
polls/templates/polls/index.html에 다음 코드를 붙여넣자.
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
위의 template을 이용하기 위해
polls/view.py 를 다음과 같이 수정하자.
from django.http import HttpResponse
from django.template import loader
from .models import Question
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
template = loader.get_template('polls/index.html')
context = {
'latest_question_list': latest_question_list,
}
return HttpResponse(template.render(context, request))
template을 load해서 context에게 패스하는 것
context는 dictionary mapping template variable names to Python objects.
결과:
A shortcut: render()
1. Load template
2. fill a context
3. return an HttpResponse object with the result of the rendered template
Django는 이런 일련의 과정들에 대한 shortcut을 제공한다.
polls/views.py을 다음과 같이 수정하자.
from django.shortcuts import render
from .models import Question
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)
* render()의 세번째 인자는 optional
render()은 template의 HttpResponse object를 context와 함께 return
Rasing a 404 error
polls/view.py의 코드를 다음과 같이 수정하자.
from django.http import Http404
from django.shortcuts import render
from .models import Question
# ...
def detail(request, question_id):
try:
question = Question.objects.get(pk=question_id)
except Question.DoesNotExist:
raise Http404("Question does not exist")
return render(request, 'polls/detail.html', {'question': question})
결과:
A shortcut: get_object_or_404()
polls/views.py를 다음과 같이 수정하자.
from django.shortcuts import get_object_or_404, render
from .models import Question
# ...
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})
Template system 사용하기
polls/templates/polls/detail.html을 다음과 같이 수정하자.
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>
Template system은 variable attributes에 접근하기 위해 dot-lookup syntax를 사용한다.
예) {{ question.question_text }}
먼저 question object에 대해 dictionary lookup을 한다.
실패할 경우, attribute lookup을 한다. -> 예제에선 여기서 끝남
또 실패할 경우, list-index lookup을 한다.
Method-calling은 {% for %} loop에서 일어난다.
Hardcoded된 Template의 URLs 지우기
우리는 polls.urls 모듈에 path() function에 name argument를 정의했으므로
{% url %} template tag를 사용해서 url configuration에 정의된 특정 url path에 대한 의존성을 지울 수 있다.
polls/templates/polls/index.html의 코드를 다음과 같이 수정하자.
# ...
<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
# ...
이게 가능한 이유는 polls.urls 모듈에 url definition을 해놨기 때문이다.
만약 polls/specifics/12/와 같이 polls detail view의 url을 바꾸고 싶다면
polls/urls.py를 다음과 같이 바꾸면 된다.
# ...
path('specifics/<int:question_id>/', views.detail, name='detail'),
# ...
결과:
Namespacing URL names
Project에는 여러개의 app들이 있을 수 있다.
그렇다면 Django가 {% url %} template tag를 사용할 때
어떤 app view에서 url을 생성하는지 구분할 수 있을까?
답은 URLconf에 namespaces를 추가하는 것이다.
polls/urls.py에 app_name을 추가해보자.
from django.urls import path
from . import views
app_name = 'polls' # 이 부분 추가
urlpatterns = [
path('', views.index, name='index'),
path('/', views.detail, name='detail'),
path('/results/', views.results, name='results'),
path('/vote/', views.vote, name='vote'),
]
그리고 polls/index.html을 다음과 같이 바꾸자
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
끝!