728x90
반응형
이전 글에서는 HttpResponse() 함수를 사용할 때 HTML을 하드코딩에서 넘겼음.
- 별로 좋은 방법이 아님
- 웹 페이지 코드와 파이썬 코드를 분리하는 것이 바람직함
템플릿(Template)
Django의 템플릿은 문서의 표시를 데이터와 분리하기 위한 텍스트 문자열임
- 자리표시 - 문서를 표시하는 방법을 조절
- 기본로직(탬플릿 태그) - 다양한 비트 정의
- 모든 텍스트 기반 형식을 생성할 수 있음
Django 프로젝트는 하나 또는 여러 개의 템플릿 엔진으로 구성될 수 있음
DTL(Django Template Language) 자체 템플릿 시스템을 위한 빌트인 백엔드를 제공
사용 과정
- 원시 템플릿 코드를 문자열로 제공해 템플릿 객체를 만듬
- 주어진 변수 세트를 사용해 템플릿 객체의 render() 메서드 호출
- 완전히 렌더링된 템플릿이 문자열로 반환, 모든 변수와 템플릿 태그는 콘텍스트에 따라 계산
템플릿 객체 만들기
템플릿 클래스는 django.template 모듈에 있고 생성자는 원시 템플릿 코드인 하나의 인수를 취함
- Template()
템플릿 코드에 구문 오류가 있는 경우 Template()을 호출하면 TemplateSyntaxError 예외가 발생함
from django.template import Template
# 객체 = Template(템플릿 문자열)
t = Template('My name is {{ name }}.')
템플릿 렌더링
템플릿 객체가 있으면 콘텍스트 정보를 지정해 데이터를 전달 할 수 있음.(django.template 모듈에 있음)
- Context()
from django.template import Template,Context
t = Template('My name is {{ name }}.')
c = Context({'name':'Pupbani'})
name 변수에 Pupbani를 지정함
이렇게 템플릿, 콘텍스트 객체를 만들면 render() 메서드를 호출함
t.render(c)
이렇게 렌더링 된 템플릿은 HttpResponse()로 전달해 뷰에 표시할 수 있음
from django.template import Template, Context
def temp(request):
t = Template('My name is {{ name }}.')
c = Context({'name':'Pupbani'})
return HR(t.render(c))
if/else - {% if %} {% endif %} 태그
- 변수를 평가하고, 해당 변수가 True이면 시스템은 {% if %}와 {% endif %} 사이를 표시함
def condi1(request):
html = """{% if num > 20 %}
<h1>참!</h1>
{% else %}
<h1>거짓!</h1>
{% endif %}"""
t = Template(html)
c = Context({'num':30})
return HR(t.render(c))
- {% elif %}를 사용해 여러개의 조건문을 만들 수 있음
def condi2(request):
html = """{% if num < 10 %}
<h1>{{ num }}은 한자리 숫자</h1>
{% elif num >= 10 %}
<h1>{{ num }}은 두자리 숫자</h1>
{% endif %}"""
t = Template(html)
c = Context({'num':30})
return HR(t.render(c))
for - {% for %} {% endfor %} 태그
- 각 시퀀스의 각 항목을 반복할 수 있음
- {% empty %}를 사용하면 해당 리스트가 비어있는 경우, 출력할 내용을 정의할 수 있음
- 특수한 변수들
forloop.counter | - 루프가 입력된 횟수(1부터) - forloop.counter0 - 0부터 시작 |
forloop.revcounter | - 루프의 나머지 항목 수(0 포함) - forloop.revcounter0 - 0 제외 |
forloop.first | - 루프가 처음일 경우 True |
forloop.last | - 루프가 마지막일 경우 True |
forloop.parentloop | - 부모 루프에 대한 forloop 객체에 대한 참조 |
def forloop(request):
html = """{% for name in names%}
<table border = 1>
<tr><td>{{ forloop.counter }}</td>
<td>{{ name }}</td></tr>
</table>
{% endfor %}"""
t = Template(html)
c = Context({'names':['Pupbani','Redbani','Yellbani']})
return HR(t.render(c))
주석 - {# 주석 #} 태그
- 주석 부분은 출력되지 않음
- 주석 태그는 중첩되지 않음
def condi2(request):
html = """{% if num < 10 %}
<h1>{{ num }}은 한자리 숫자{# 주석이용 #}</h1>
{% elif num >= 10 %}
<h1>{{ num }}은 두자리 숫자{# 주석이용 #}</h1>
{% endif %}"""
t = Template(html)
c = Context({'num':30})
return HR(t.render(c))
템플릿 필터
- 변수가 표시되기 전에 변수의 값을 변경하는 간단한 방법
- 파이프( | ) 문자를 사용
def filter1(request):
html = '<h1>{{ name|upper }}</h1>'
t = Template(html)
return HR(t.render(Context({'name':'pupbani'})))
HTML 파일을 가져와서 템플릿 사용
- html 파일을 가져오려면 Django의 get_template() 함수를 사용
- django.template.loader에 정의되 있음
- settings.py의 TEMPLATES를 확인해보기
- BACKEND : 장고의 템플릿 백엔드 API를 구현하는 템플릿 엔진 클래스에 대한 점으로 구분된 파이썬 경로
- DIRS : 기본적으로 비어있음, 엔진이 템플릿 소스 파일을 검색할 순서로 검색해야 하는 디렉터리 리스트를 정의
- APP_DIRS : 엔진이 설치된 응용 프로그램 내에서 템플릿을 찾아야 하는지의 여부를 알려줌, 규약에 따라 True일 경우 장고 템플릿은 각 INSTALLED_APPS에서 "templates" 하위 디렉터를 찾음
- OPTIONS : 백엔드 관련 설정 포함
# HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Django</title>
</head>
<body>
<h1>{{ name }}</h1>
<table border="1">
{% for i in strings %}
<tr>
<th>{{ forloop.counter }}</th>
<td>{{ i }}</td>
</tr>
{% endfor %}</table>
</body>
</html>
from django.http import HttpResponse as HR
from django.template import *
from django.template.loader import get_template
def hello(request):
t = get_template('index.html')
contexts = {'name':'Pupbani','strings':['hello','good','bye']}
return HR(t.render(contexts))
- get_template을 사용하여 html을 불러오면 context를 사전 형태의 변수로 전달해야 함
- Context 함수 사용 X
render()
- 한줄의 코드로 모든 작업(HttpResponse, Template, Context)을 하기 위한 render()를 제공함
- django.shortcuts 모듈에 정의
- render(request, Template name , Context)
- 첫번째 매개변수 - 요청
- 두번째 매개변수 - 사용할 템플릿 이름
- 세번째 매개변수 - Context, 인수 제공을 하지 않으면 빈 딕셔너리를 사용
from django.shortcuts import render
def hello(request):
contexts = {'name':'Pupbani','strings':['hello','good','bye']}
return render(request,'index.html',contexts)
템플릿 내장/상속
- {% include %}를 사용해 다른 템플릿의 내용을 포함할 수 있음
# include1.html
<div>
<h1>Include Test</h1>
<h2>템플릿 포함</h2>
</div>
#include.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Django</title>
</head>
<body>
<h1>템플릿 포함 테스트</h1>
{% include "include1.html" %}
</body>
</html>
from django.http import HttpResponse as HR
from django.template.loader import get_template
def temp(request):
t = get_template('include.html')
contexts = {}
return HR(t.render(contexts))
- 템플릿 상속은 다음과 같은 과정을 수행함
- html을 작성하고 {% block content %} {% endblock %} 사이의 부분을 자식에서 작성하도록 함
- 자식 html은 {% extends "부모.html" %}를 사용해 상속을 표시하고 {% block content %} {% endblock %}로 구현을 함
# base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Django</title>
</head>
<body>
<h1>템플릿 상속</h1>
<p>부모 html</p>
{% block content %}
<!-- 여기가 자식이 구현할 부분 -->>
{% endblock %}
<p>부모 html</p>
</body>
</html>
# parent.html
{% extends "base.html" %}
{% block content %}
<h1>자식 부분</h1>
<p>상속 완료</p>
{% endblock %}
from django.shortcuts import render
def inh(request):
return render(request,'parent.html')
728x90
반응형
'Back-end & Server > Django' 카테고리의 다른 글
[Django] 폼(Form) (0) | 2023.01.20 |
---|---|
[Django] Admin 사이트 (0) | 2023.01.16 |
[Django] 모델 (0) | 2023.01.16 |
[Django] 뷰와 URLconfs (0) | 2022.12.28 |
[Django] Django 시작하기 (0) | 2022.12.28 |