지난 게시글에 이은 장고 공식 튜토리얼 투표하기 따라하기 3편입니다 :)
역시 크레이 입맛(?)에 맞게 일부 가감한 부분이 있습니다.
지난 게시글 : https://itadventure.tistory.com/665
https://docs.djangoproject.com/en/5.0/intro/tutorial03/
상세 페이지 URL 만들기
지금까지는 첫페이지 주소만 만들었습니다.
http://127.0.0.1:8000/polls/ URL 주소가 바로 그것인데요.
이제 실제 데이터를 표시하는 페이지를 만들어 볼 차례입니다.
장고의 URL 주소는 요새 현대적 프레임 워크 추세에 따라
아래와 같은 단순한 URL 주소 지원이 가능한데요.
예)
http://127.0.0.1:8000/polls/글번호/
http://127.0.0.1:8000/polls/글번호/results/
http://127.0.0.1:8000/polls/글번호/vote/
주소가 매우 간결해 보기도 좋고 그 느껴지는 분위기가 매우 우아하지 않으신가요 ? :)
이제 그 규칙을 만들어 봅시다.
polls/views.py 파일을 열어, detail, results, vote 함수를 추가해 줍니다.
from django.http import HttpResponse
def index(request):
return HttpResponse("투표용 서브 첫페이지.")
def detail(request, question_id):
return HttpResponse("설문지 %s 번 페이지입니다." % question_id)
def results(request, question_id):
response = "설문지 %s 번 결과 페이지입니다.."
return HttpResponse(response % question_id)
def vote(request, question_id):
return HttpResponse("귀하께서는 %s 번 설문중이시군요." % question_id)
그리고 이 함수들을 각각 URL을 연결하겠습니다.
polls/urls.py 파일을 열어 각 URL 주소를 연결해 줍니다.
from django.urls import path
from . import views
urlpatterns = [
# /polls/
path("", views.index, name="index"),
# 예시: /polls/5/
path("<int:question_id>/", views.detail, name="detail"),
# 예시: /polls/5/results/
path("<int:question_id>/results/", views.results, name="results"),
# 예시: /polls/5/vote/
path("<int:question_id>/vote/", views.vote, name="vote"),
]
이제 장고 웹서버를 작동하여 URL 연결을 확인해보겠습니다.
터미널에 서버가 작동중이라면 Ctrl + C 키를 눌러 중지하고 난 다음,
다시 웹 서비스를 시작합니다.
python manage.py runserver
그리고 지난 번에 추가했던 투표의 id값을 기준으로 아래와 같이 URL 에 접속합니다.
만약 id값이 4였다면 주소는 http://127.0.0.1:8000/polls/4/ 입니다.
아래와 같은 결과 페이지가 등장하였나요? 그렇다면 제대로 된 것입니다.
내친 김에 다른 URL 도 접속해 확인해볼까요?
http://127.0.0.1:8000/polls/4/results/
http://127.0.0.1:8000/polls/4/vote/
실제 목록 페이지
이제 실제 설문지 목록이 표시되는 페이지를 꾸며볼텐데요.
http://127.0.0.1:8000/polls/ 에 해당하는 index 함수를 수정하면 됩니다.
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 = "<br/>".join([q.question_text for q in latest_question_list])
return HttpResponse(output)
:
그리고 http://127.0.0.1:8000/polls/ 페이지에 접속하면
지난 게시글의 장고 인터프리터처럼 2개의 설문지 목록이 나열됩니다.
실제 데이터가 홈페이지에 표시가 된 것이지요.
하지만 이 것은 장고의 기능을 제대로 발휘한 것이 아닌데요.
장고는 MVC 패턴에 따라 장고 개발자가 다룰 기능 파일과
퍼블리셔가 다룰 HTML 파일을 분리할 수 있습니다.
이 HTML 파일을 템플릿이라고 합니다.
디자인을 예쁘게 하려면 HTML 소스가 길어지기 때문에
복잡성을 낮추기 위해서라도 이 부분은 매우 중요합니다.
템플릿을 분리해보도록 합시다.
템플릿 파일을 저장할 폴더를 먼저 생성해야 하는데요.|
polls 폴더 하위에 templates 폴더를 만들고 다시 그 하위에 polls 폴더를 생성합니다.
그리고 그 하위에 index.html 파일을 만듭니다
금방 만든 polls/templates/polls/index.html 파일을 아래와 같이 꾸며줍니다.
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8" />
<title>설문 목록</title>
</head>
<body>
<h1>설문 리스트</h1>
{% 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>설문 목록이 없습니다.</p>
{% endif %}
</body>
</html>
그리고 polls/views.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))
:
이 후 http://127.0.0.1:8000/polls/ URL 에 접속하면 아래와 같이 예쁜 설문 목록이 표시되는 것을 볼 수 있습니다.
소스는 되도록 간결하면 더 좋은데요.
장고의 shortcuts 모듈을 이용하면 더욱 소스가 간결해 집니다.
polls/views.py 파일의 앞 부분을 아래와 같이 수정해도 동일하게 작동합니다.
from django.http import HttpResponse
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)
:
이제 설문 항목 페이지를 꾸며보겠습니다.
선택 기능은 나중에 구현하기로 하고, 설문 제목과 설문 항목을 보여주기만 할텐데요.
이를 위해 detail.html 템플릿 파일을 먼저 추가합니다.
polls/templates/polls/detail.html
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8" />
<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>
뷰에서 이 페이지를 연결해 줄텐데요.
특별히 404 오류 페이지 기능을 추가로 접목해 보겠습니다.
404 오류 페이지는 '존재하지 않는 오류 페이지'라는 뜻인데요.
존재하지 않는 투표 게시글 번호를 지정했을 때 처리를 해주는 부분입니다.
polls/view.py 파일에서
from django.shortcuts ... 라 표시된 행을 아래와 같이 수정하고,
:
from django.shortcuts import get_object_or_404, render
:
detail() 함수를 아래와 같이 수정합니다.
:
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/index.html 파일에는 아래와 같이 투표 페이지로 이동하는 링크가 '/polls/ 어쩌고로 되어 하드코딩되어 있습니다.
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
이러한 코드는 템플릿 파일이 많이 있는 경우 polls 폴더 이름을 바꾸려고 해도 수정할 파일이 너무 많아 엄두가 안 나는 문제가 있는데요.
처음부터 urls.py 의 urlpattern 에 정의한 name 값을 이용하면, 해당 걱정을 덜 수 있습니다.
위 소스를 아래와 같이 변경해도 기능은 동일하게 작동하는데요.
<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
그것은 urls.py 에 정의한 아래 코드 때문입니다.
path("<int:question_id>/", views.detail, name="detail"),
한 단계 더 나아가봅시다.
이 예제에서는 polls 앱 (서브 폴더) 만 존재하지만, 앱이 2, 3개 있다면 서로 이름이 겹칠 수 있습니다.
그래서 네임 스페이스를 정의하여 이름을 다음과 같이 사용할 수 있도록 해주어야 하는데요.
'polls.detail'
네임 스페이스는 app_name 으로 정의해 주면 됩니다.
urls.py 파일을 아래와 같이 수정하고,
from django.urls import path
from . import views
app_name = "polls"
urlpatterns = [
# /polls/
path("", views.index, name="index"),
# 예시: /polls/5/
path("<int:question_id>/", views.detail, name="detail"),
# 예시: /polls/5/results/
path("<int:question_id>/results/", views.results, name="results"),
# 예시: /polls/5/vote/
path("<int:question_id>/vote/", views.vote, name="vote"),
]
index.html 파일의 링크도 아래와 같이 수정합니다.
이제 기능은 동일하게 작동합니다.
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
필요하신 분에게 도움이 되셨는지 모르겠습니다 :)
오늘은 글을 2개나 올리네요. 방문해주신 모든 분들께 감사드립니다.