[Python] django 장고 템플릿
이제는 요청과 응답을 저장해 둔 데이터를 조회하여 웹 브라우저에 출력하고자 합니다.
데이터를 DB에서 조회하고 불러와서 웹 브라우저에 HTML 코드로 변환하여 출력해야 합니다.
하지만, 파이썬 코드는 브라우저에서 동작하지 않습니다. 브라우저는 알다시피 HTML 코드만 동작합니다.
장고에 내장된 템플릿 태그(template tags)는 파이썬 코드를 HTML로 바꿔주어, 빠르고 쉽게 동적인 웹 사이트를 만들 수 있게 도와줍니다.
그럼 앞전에 작성해 둔 질문들을 DB에서 조회하여 웹브라우저 출력될 수 있도록 구현해 봅시다.
먼저, 템플릿을 보관할 디렉토리를 생성해 주어야 합니다.
1. 템플릿 생성
mysite\ 아래에 templates 디렉토리를 생성합니다.
해당 프로젝트가 이 템블릿 디렉토리의 저장경로를 알 수 있게 config/settings.py 파일의 TEMPLATES 항목에 설정합니다.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], #수정
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
DIRS 부분에 []을 [os.path.join(BASE_DIR, 'templates')] 라고 수정합니다.
DIRS는 템플릿 디렉터리를 여러 개 등록할 수 있도록 리스트로 되어 있습니다. BASE_DIR은 c:\projects\mysite 입니다. setting.py 파일 윗부분에 정의되어 있습니다.
추가로 pybo 앱에서 사용할 템플릿을 mysite/templates 디렉터리 아래에 pybo 이름으로 생성합니다.
그리고 실제로 사용하는 템플릿 파일을 만들어야 합니다.
파일명은 question_list.html 입니다. 경로는 mysite\templates\pybo 입니다.
templates\pybo 디렉터리에서 마우스 우클릭 > New > HTML File 클릭합니다.
이름을 question_list.html 로 작성합니다.,
그리고 pybo/question_list.html 파일을 기존에 작성되어 있는 거는 다 삭제하시고 다음과 같이 작성하고 저장합니다.
{% if question_list %} #question_list가 있다면
<ul>
{% for question in question_list %} #question_list를 순회하며 순차적으로 하나씩 question에 대입
<li><a href="/pybo/{{ question.id }}/">{{ question.subject }}</a></li> #id와 제목을 출력
{% endfor %}
</ul>
{% else %}
<p>질문이 없습니다.</p>
{% endif %}
{%와 %}로 둘러싸인 문장을 템플릿 태그라고 합니다.
템플릿 태그
장고에서 사용하는 템플릿 태그는 다음 3가지 유형만 알면 됩니다.
1) 분기
분기문 태그의 사용법은 다음과 같습니다.
{% if 조건문1 %}
<p>조건문1에 해당되는 경우</p>
{% elif 조건문2 %}
<p>조건문2에 해당되는 경우</p>
{% else %}
<p>조건문1, 2에 모두 해당되지 않는 경우</p>
{% endif %}
파이썬의 if문과 다를바가 없습니다. 다만 항상 {% endif %} 태그로 닫아주어야 합니다.
2) 반복
반복문 태그 사용법은 다음과 같습니다.
{% for item in list %}
<p>순서: {{ forloop.counter }} </p>
<p>{{ item }}</p>
{% endfor %}
파이썬의 for문과 비슷합니다. 역시 항상 {% endfor %} 태그로 닫아주어야 합니다. 그리고 템플릿 for문 안에서는 다음과 같은 forloop 객체를 사용할 수 있습니다.
3) 객체 출력
객체를 출력하이 위한 태그의 사용법입니다.
{{ 객체.속성 }}
예)
{{question.id}}, {{question.subject}}
2. 뷰 파일 수정
DB에 저장되어 있는 데이터가 출력될 수 있도록 이번엔 pybo/views.py 파일의 index함수를 다음과 같이 수정합니다.
from django.shortcuts import render
from .models import Question
def index(request):
question_list = Question.objects.order_by('-create_date')
context = {'question_list': question_list}
return render(request, 'pybo/question_list.html', context)
질문 목록 데이터는 Question.objects.order_by('-create_date')로 조회 후 question_list 변수에 대입합니다.
order_By는 조회 결과 값을 정렬하는 함수입니다.
-create date는 작성일시를 역순으로 정렬하라는 뜻입니다. 대소문자를 구분하니 소문자로 작성해 주셔야 합니다.
- 기호가 붙어 있으면 역방향, 없으면 순방향 정렬을 의미합니다.
render 함수는 파이썬 데이터를 템플릿에 적용하여 HTML로 반환하는 함수입니다.
즉, 위에서 사용한 render 함수는 질문 목록으로 조회한 question_list 데이터를 pybo/question_list.html 파일에 적용하여 HTML을 생성한 후 리턴합니다.
setting.py 파일을 수정한 것이기 때문에 적용을 위해서는 서버를 재시작해줘야 합니다.
서버 재시작한 후에 http://localhost:8000/pybo 에 접속하면 아래와 같이 출력되는 것을 확인할 수 있습니다.
해당 질문을 클릭하면 아래와 같이 id 같이 하위 페이지로 열리는 것을 확인하실 수 있습니다.
위와 같이 오류가 표시된 이유는 http://localhost:8000/pybo/2 와 같은 페이지에 대한 URL 매핑이 없기 때문입니다.
3. URL 매핑
URL 매핑을 위해서 mysite/pybo/urls.py 파일을 수정합니다.
path('', views.index), 아래에 path('<int:question_id>/', views.detail), 를 추가합니다.
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
path('<int:question_id>/', views.detail), # << 추가
]
http://localhost:8000/pybo/2/ 페이지가 요청되면 여기에 등록된 매핑 룰에 의해
http://localhost:8000/pybo/<int:question_id>/가 적용되어 question_id에 2가 저장되고 views.detail 함수가 실행됩니다.
이제 views.detail 함수를 정의해 줍니다.
mystie/pybo/views.py 파일로 이동합니다
아래와 같이 detail 함수를 정의합니다.
def detail(request, question_id):
question = Question.objects.get(id=question_id)
context = {'question':question}
return render(request, 'pybo/question_detail.html', context)
question_id 매개변수에 따라 화면을 출력해줍니다.
http://localhost:8000/pybo/2/ 페이지가 요청되면 매개변수 question_id에 2가 세팅되어 detail 함수가 출력됩니다.
4. 템플릿 파일 수정
이제 http://localhost:8000/pybo/2/ 페이지에 사용될 html 파일을 만들어 주어야 합니다.
템플릿 파일을 만드는 것이므로 경로는 mysite/templates/pybo 이고 파일의 이름은 question_detail.html 으로 합니다.
내용은 아래와 같이 작성하겠습니다.
<h1>{{ question.subject }}</h1>
<div>
{{ question.content }}
</div>
저장 후 http://localhost:8000:/pybo/2/ 페이지를 다시 요청하면 아래와 같이 정상 출력될 것입니다.
5. URL 매핑이 없을 경우의 오류 페이지
예를 들어, http://localhost:8000/pybo/30/ 페이지를 요청할 경우 아래와 같이 오류가 발생합니다.
이 오류는 question_id 값이 30이기 때문에 Qustion.odject.get(id=30) 이 호출되어 발생한 오류 입니다.
이때 브라우저에 전달되는 오류 코드는 500입니다.
이렇게 없는 데이터를 요청할 경우 500 오류 페이지 보다는 "Not Found (404)" 페이지를 리턴하는 것이 웹 개발에 바람직합니다.
[ HTTP 주요 응답코드의 종류 ]
오류코드 | 설명 |
200 | 성공 (OK) |
500 | 서버오류 (Internal Server Error) |
404 | 서버가 요청한 페이지(Resource)를 찾을 수 없음 (Not Found) |
위와 같이 없는 페이지를 요청할 경우 500 페이지 대신 404 페이지를 출력하도록 deatil 함수를 다음과 같이 수정합니다.
상단에 get_object_or_404 를 추가합니다.
from django.shortcuts import render, get_object_or_404
그리고 detail 함수에 아래와 같이 수정합니다.
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
context = {'question': question}
return render(request, 'pybo/question_detail.html', context)
Question.object.get(id=question_id)를 get_object_or_404(Question, pk=question_id)로 바꾸었습니다.
이렇게 수정하고 없는 페이지를 다시 한번 요청하면 500대신 404가 리턴되어 404 오류 페이지를 출력합니다.
정리
정리하자면, 템플릿 파일이란 확장자가 html인 파일이고
템플릿 파일의 역할은 파이썬의 코드를 웹 브라우저가 해석할 수 있게 변경해주는 역할입니다.
http://localhost:8000/pybo 페이지의 템플릿 파일은 question_list.html 입니다.
http://localhost:800/pybo/ 요청이 오면 제일 먼저 mysite/pybo/urls.py 을 참고합니다.
urlpatterns = [
path('', views.index),
path('<int:question_id>/', views.detail),
]
위와 같이 http://localhost:8000/pybo/ 페이지를 요청하면 views.py의 index 함수를,
http://localhost:8000/pybo/id/ 페이지를 요청하면 views.py의 detail 함수를 호출합니다.
자 그럼 이제 views.py 파일을 확인합니다.
def index(request):
question_list = Question.objects.order_by('-create_date')
context = {'question_list': question_list}
return render(request, 'pybo/question_list.html', context)
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
context = {'question': question}
return render(request, 'pybo/question_detail.html', context)
위와 같이 정의되어 있습니다.
index 함수의 리턴값은 question_list.html을 HTMl 로 변환한 값입니다.
(render 함수는 파이썬 데이터를 템플릿에 적용하여 HTML로 반환하는 함수입니다.)
이렇게 하여 화면에 출력되는 것입니다.
http://localhost:8000/pybo 호출 -> urls.py -> views.py
점프 투 장고, 장고걸스 등을 바탕으로 공부한 내용을 정리한 글입니다. 더 자세한 사항은 책을 참고 부탁드립니다.
'IT > Python' 카테고리의 다른 글
[Python] django URL 별칭 만들기 (0) | 2022.09.02 |
---|---|
[Python] django 템플릿 태그 (0) | 2022.08.31 |
[Python] django 장고 관리자(admin) (0) | 2022.08.29 |
[Python] django 모델을 이용한 데이터베이스 처리 (0) | 2022.08.29 |
[Python] django 앱(App) 만들기 urls.py 와 views.py (0) | 2022.08.29 |
댓글