현재 view의 detail함수는 question_id에 따라서 화면을 보여준다. 만약 question_id가 없는 경우에는 404에러를 띄우도록 하겠다.
polls/views.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})
일단 예제를 동작하기 위해 detail.html에 다음과 같이 추가하였다.
polls/templates/polls/detail.html
{{question}}
http://127.0.0.1:8000/polls/1/ 에 접속하는 경우 다음과 같은 화면이 출력된다.
하지만 http://127.0.0.1:8000/polls/2/ 에 접속하면
다음과 같이 404에러를 발생시킨다.
try catch문을 사용하는 것 대신 get_object_or_404
를 사용할 수 있다.
polls/views.py
from django.shortcuts import get_object_or_404, render
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, "polls/detail.html", {"question": question})
이번에는 한 question에 대해 이를 외래키로 갖는 다른 choice들을 활용해 볼 것이다.
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>
detail.html을 다음과 같이 수정하였다. question의 question_text
와 question을 외래키로 가지는 choice들을 모두 출력한다.
admin을 사용해서 choice들을 만들어보자.
polls/admin.py
from django.contrib import admin
from .models import Question, Choice
admin.site.register(Question)
admin.site.register(Choice)
admin에 다음과 같이 choice에 대한 권한을 추가한다.
이제 관리자 페이지에서 다음과 같이 choice를 추가할 수 있다. choice 1, 2, 3을 추가해주자.
다음과 같이 choice들이 출력되는 것을 확인할 수 있다.polls/index.html을 보게되면
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
이렇게 URL이 하드코딩 되어있다. 이렇게 되면 URL 변경시 URL이 있는 템플릿 코드들을 변경해야 한다. 장고에서는 url마다 name을 명시할 수 있기 때문에 다음과 같이 변경하면 수정의 영향에서 자유로워 진다.
URLconf에 이름공간(namespace)를 추가한다. polls/urls.py에 app_name을 추가하여 어플리케이션의 이름공간을 설정한다.
polls/url.py
from django.urls import path
from . import views
app_name = 'polls'
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/index.html
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
다음과 같이 index.html을 수정할 수 있다.