뷰(Views)
뷰는 말 그대로 '보여주는' 역할을 한다. HTML 페이지 또는 모델 등에서 받아온 데이터를 사용자에게 노출시켜 준다. mysite 아래에 있는 urls.py에서 해당 URL에 요청이 오면, views.py에서 지정된 함수에 의해 해당 화면을 노출시킨다.
# mysite/urls.py
from django.contrib import admin
from django.urls import path, include
# polls/ URL 뒤에는 polls 폴더 내 urls.py 설정을 따름
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]
# mysite/polls/urls.py
from django.urls import path
from . import views
# polls/ URL 뒤에 아무것도 없을 시 >>> index에 해당하는 함수 실행
urlpatterns = [
path('', views.index, name='index'),
]
from django.shortcuts import render
from django.http import HttpResponse
from .models import Question
# 가장 최근 질문 5개를 최신순으로 보여줌 (문자열 형태로)
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)
위와 같이 URL과 views.py의 설정을 마친 뒤 서버를 실행시켜 /polls로 이동한다면 아래와 같이 노출된다.
템플릿 (Templates)
뷰가 사용자에게 노출되는 화면을 전달해주는 역할이라는 것을 위 코드를 통해 알 수 있었다. 하지만 웹 페이지는 보통 저렇게 구성하지 않는다. HTML, CSS 등을 활용해 좀 더 보기 좋은 화면을 사용자에게 제공한다. 이를 위해 사용하는 것이 템플릿이다.
polls 폴더 안에 templates/polls/index.html 파일을 생성해보자.
<-- polls/templates/polls/index.html -->
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li>{{ question.question_text }}</li>
{% endfor %}
</ul>
{% else %}
<p>설문조사가 없습니다.</p>
{% endif %}
질문 리스트를 간단하게 점 표시와 함께 보여주는 html 코드를 작성했다.
그리고 views.py에서도 위 html 파일을 불러들일 수 있게 수정해주자.
# mysite/polls/views.py
# 템플릿 사용을 위해서는 render를 임포트 해주어야 한다.
from django.shortcuts import render
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])
# render는 templates 폴더 내에서 아래에 해당하는 파일을 찾는다.
return render(request, 'polls/index.html', {
'latest_question_list': latest_question_list,
})
그 다음 다시 서버를 실행해 화면을 확인해보자.
리스트 형태로 질문 레코드들이 노출되는 것을 확인할 수 있다.
템플릿에서 제어문 사용하기
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li>{{ question.question_text }}</li>
{% endfor %}
</ul>
{% else %}
<p>설문조사가 없습니다.</p>
{% endif %}
위와 같이 html 템플릿 파일에서도 if, else, for문을 사용할 수 있다. 대신 사용하기 위해서 {% %}와 같은 태그를 붙여주어야 한다.
상세(detail) 페이지 만들기
흔히 게시판 같은 형태의 웹 사이트들은 각 게시글을 확인하는 상세 페이지 URL에 각 게시글에 해당하는 숫자를 넣고는 한다.
ex) https://minding-deep-learning.tistory.com/233
이와 같은 페이지를 상세 페이지라고 하는데, 위 질문 레코드의 id값을 인자로 받아 URL에 적용하고, 해당 페이지에는 질문에 대한 답변들이 노출되도록 구현해보려고 한다. 먼저 해당 URL을 등록해줘야 한다.
# mysite/polls/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
# question_id를 인자로 받는 url(정수형 숫자)이 요청되면 detail 함수 실행
path('<int:question_id>/', views.detail, name='detail'),
]
그리고 views.py 수정을 통해 어떤 데이터가 템플릿을 통해 보여질 것인지 설정해주자.
# mysite/polls/urls.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Question
...
# 요청을 받을 때 question의 id값도 같이 받고, 해당 정보를 question에 담아 반환
def detail(request, question_id):
question = Question.objects.get(pk=question_id)
return render(request, 'polls/detail.html', {'question': question})
그리고 템플릿까지 생성해준다.
<-- mysite/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) 페이지로 향하는 링크 추가하기
앞서 위 이미지 예시처럼 리스트 형태로만 구성된 index 페이지에서 상세 페이지로 이어질 수 있도록, 상세 페이지 링크를 추가하려고 한다.
먼저 index.html을 다음과 같이 수정한다. 링크를 추가 하기위해 a태그를 사용한다.
{% if latest_question_list %}
<h1>최근 질문 목록</h1>
<ul>
{% for question in latest_question_list %}
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>no questions</p>
{% endif %}
{% url 'polls:detail' question.id %}는 polls라는 앱의 detail이라는 이름을 가진 path에 question id값을 넣어 링크를 가져온다는 뜻이다. 이를 사용하기 위해서는 urls.py를 다음과 같이 수정해줘야 한다.
from django.urls import path
from . import views
# app name 지정
app_name = 'polls'
urlpatterns = [
path('', views.index, name='index'),
path('<int:question_id>/', views.detail, name='detail'),
]
위와 같이 app 이름을 지정해주어야 위 코드가 정상적으로 작동한다.
404 에러 처리하기
사용자가 url에 잘못 입력하는 등 잘못된 요청이 서버에 전달됐을 때 노출되는 에러다. 우선 현재 어떤 에러가 발생하고 있는지 알아보자. url에 123을 입력해 현재 없는 question을 조회해보았다.
그 결과 DoesNotExist Error가 발생했고, 크롬의 개발자 도구를 통해 확인해보니 응답으로는 500 에러 코드가 반환되었다. 이는 '서버 내부 문제'라는 뜻으로, 알 수 없는 문제로 에러가 발생했다는 뜻이다.
이를 원인을 알 수 있는 404 에러코드(잘못된 요청)으로 반환해 주려고 한다. 아래와 같이 문제가 되는 부분에 try, except 문을 이용할 수 있다.
또는 django가 제공하는 shortcuts 기능을 이용할 수도 있다. get_object_or_404 함수를 이용하면 된다. 해당 object를 가져오거나, 가져올 수 없다면 404에러를 반환하는 것이다.
from models.py import *
from django.http import HttpResponse
from django.http import Http404
from django.shortcuts import render , get_object_or_404
...
def detail(request, question_id):
"""
try:
question = Question.objects.get(pk=question_id)
except Question.DoesNotExist:
raise Http404("Question does not exist")
"""
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})
'Minding's Programming > Django' 카테고리의 다른 글
[Django] Admin 페이지 편집 (0) | 2024.10.10 |
---|---|
[Django] 폼(Forms) (0) | 2024.10.08 |
[Django] 모델 메소드(Model Method) (1) | 2024.10.08 |
[Django] 모델 필터링(Model Filtering) (2) | 2024.10.07 |
[Django] Django Shell 사용해보기 (0) | 2024.10.07 |