어플리케이션과 어드민이 완성되었으니 이제 투표(polls) 어플리케이션에 공개 인터페이스인 뷰(view)를 추가할 차례!
뷰는 장고 어플리케이션이 특정 기능과 템플릿을 제공하는 웹페이지의 한 종류
예를 들어, 블로그 어플리케이션의 경우
여기서는 총 4개의 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)
path() 호출을 추가해 새로운 뷰를 polls.urls 모듈르 연결
# polls/urls.py
from django.urls import path
from . import views
urlpatterns = [
# ex: /polls/
path('', views.index, name='index'),
# ex: /polls/5/
path('<int:question_id>/', views.detail, name='detail'),
# ex: /polls/5/results/
path('<int:question_id>/results/', views.results, name='results'),
# ex: /polls/5/vote/
path('<int:question_id>/vote/', views.vote, name='vote'),
]
사용자가 웹사이트의 페이지를 요청할 때 예를 들어 /polls/34/
를 요청하면, Django는 mysite.urls 파이썬 모듈을 불러온다.
mysite.urls에서 urlpatterns라는 변수를 찾고, 순서대로 패턴을 따라간다. 일치하는 패턴을 찾으면 일치하는 텍스트를 버리고 남은 텍스트를 URLconf로 전달해 남은 처리를 진행한다.
뷰는 페이지의 내용이 담긴 HttpRespone 객체를 반환하거나 Http404 같은 예외를 발생하게 해야한다
Django에 필요한 것은 HttpResponse 객체 혹은 예외
# polls/views.py
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)
뷰에서 사용할 수 있는 템플릿을 작성해 파이썬 코드로부터 디자인을 분리하도록 템플릿 시스템을 사용한다
polls 하위에 templates 디렉토리 생성
<!-- polls/templates/polls/index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>This is title</title>
</head>
<body>
{% 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 %}
</body>
</html>
polls/views.py에 index 뷰 업데이트
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]
# polls/index.html 템플릿을 불러온 후, context를 전달
template = loader.get_template('polls/index.html')
context = {
'latest_question_list': latest_question_list,
}
return HttpResponse(template.render(context, request))
그리고 위 코드는 render()를 활용해 다음과 같이 단축이 가능하다
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)
Http404를 사용한다
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})
<!-- polls/templates/polls/detail.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>This is title</title>
</head>
<body>
{{ question }}
</body>
</html>
get_object_or_404()
를 사용해 위 코드를 단축시킬 수 있다
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})
<!-- polls/templates/polls/detail.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>This is title</title>
</head>
<body>
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>
</body>
</html>
AS_IS
<li>
<a href="/polls/{{ question.id }}/">
{{ question.question_text }}
</a>
</li>
TO_BE
<li>
<a href="{% url 'detail' question.id %}">
{{ question.question_text }}
</a>
</li>
# polls/urls.py
# 여기서 name 값이 template의 {% url %} 로 인해 호출된다
path('<int:question_id>/', views.detail, name='detail')
여러 앱의 URL을 구별하기 위해 URLconf에 이름공간을 추가한다
polls/urls/py에 아래 코드 추가
...
app_name='polls'
urlpatterns = [
...
]
그리고 polls/index.html 템플릿을 아래와 같이 변경
<li>
<a href="{% url 'polls:detail' question.id %}">
{{ question.question_text }}
</a>
</li>