[Django] 뷰(views)와 템플릿(templates)

2024. 10. 8. 15:46·Minding's Programming/Django
728x90
반응형

뷰(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})

 

 

728x90

'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
'Minding's Programming/Django' 카테고리의 다른 글
  • [Django] Admin 페이지 편집
  • [Django] 폼(Forms)
  • [Django] 모델 메소드(Model Method)
  • [Django] 모델 필터링(Model Filtering)
Minding
Minding
  • Minding
    Today's Minding
    Minding
  • 전체
    오늘
    어제
    • 울고넘는 딥러닝 (278)
      • Minding's Baseball (57)
        • MLB Statcast (29)
        • 머신러닝으로 홈런왕 예측하기 (3)
        • 야구칼럼 (12)
        • 야구 규칙, 용어 (1)
        • 2022-23 질롱 코리아 (8)
        • 류현진 등판경기 (4)
      • Minding's Programming (185)
        • 프로그래머스 코딩테스트 (21)
        • Knowledge (44)
        • Numpy & Pandas (6)
        • Excel (3)
        • Git (1)
        • Pygame (11)
        • CV (3)
        • Tensorflow tutorial (4)
        • Kaggle and Dacon (4)
        • 에러 코드 (8)
        • FastAPI (8)
        • Airflow (29)
        • Crawling (6)
        • Django (14)
        • AWS (18)
        • Spark (5)
      • Minding's Reading (30)
        • 머신러닝 딥러닝에 필요한 기초 수학 with 파이.. (2)
        • 칼만필터는 어렵지 않아 (11)
        • 밑바닥부터 시작하는 딥러닝 (6)
        • 메이저리그 야구 통계학 2e (8)
        • 논문읽기 (2)
        • 빅데이터를 지탱하는 기술 (1)
      • Minding's Life (5)
        • 주식 (4)
        • 각종 소식 (1)
  • 블로그 메뉴

    • 홈
    • Baseball
    • Programming
    • Reading
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Airflow
    넘파이
    mlb stats api
    Python
    django python
    django
    프로그래머스
    에어플로우
    질롱코리아
    메이저리그
    pygame
    KBO
    데이터분석
    머신러닝
    데이터 엔지니어
    칼만필터는어렵지않아파이썬
    코딩테스트
    칼만필터
    게임개발
    AWS
    KalmanFilter
    파이썬게임개발
    파이게임
    딥러닝
    칼만필터는어렵지않아
    MLB
    야구
    칼만필터는어렵지않아python
    FastAPI
    파이썬
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Minding
[Django] 뷰(views)와 템플릿(templates)
상단으로

티스토리툴바