Django - Template System
템플릿 시스템
템플릿에서는 로직을 표현하는 것이 아니라 사용자에게 어떻게 보여줄지에 대한 룩앤필을 표현한다.
Django 의 템플릿 시스템은 템플릿 코드를 해석하여 HTML, XML, CSV 등의 단순한 텍스트 파일로 결과물을 만들어 준다.
템플릿 변수
{{ variable }}
- 변수명은 문자, 숫자, 언더바(_)를 사용한다.
- 변수의 속성에 접근할 수 있는 도트(.) 표현식도 가능
- foo.bar 라는 변수가 있다면
- foo가 사전타입이면, foo['bar']로 해석
- 다음으로는 foo의 속성을 찾아서 bar 라는 속성이 있으면, foo.bar 로 해석
- 마지막으로 foo가 리스트이면, foo[bar]로 해석
- foo.bar 라는 변수가 있다면
- 정의가 되어 있지 않은 변수는 기본적으로 빈 문자열('')로 인식
- 이러한 기본 값을 변경하려면 settings.py 파일에서
TEMPLATE_STRING_IF_INVALID
속성을 지정한다.
- 이러한 기본 값을 변경하려면 settings.py 파일에서
템플릿 필터
템플릿 변수에 필터를 적용하여 변수의 출력 결과를 변경할 수 있다.
{{ name|lower }} // name 변수값의 모든 문자를 소문자로 바꿔주는 필터
{{ text|escape|linebreaks }}
// 필터를 체인으로 연결하는 것도 가능하다.
// 특수 문자를 이스케이프 한 후, 결과 스트링에 <p> 태그를 붙여준다.
{{ bio|truncatewords:30 }} // bio 변수값 중 앞 30개 단어만 보여주고, 줄 바꿈 문자는 없앤다.
{{ list|join:" !! " }} // ['a', 'b', 'c'] => "a !! b !! c"
{{ value|default:"nothing" }} // value가 False 이거나 없는 경우, "nothing"
{{ value|length }} // value 변수값의 길이 반환
{{ value|striptags }} // value 값에서 html 태그를 없앤다.(100% 보장 X)
{{ value|pluralize }} // value 값이 1이 아니면 복수 접미사 's'를 붙인다.
{{ value|pluralize:"es" }}
{{ value|pluralize:"y, ies" }}
{{ value|add:"2" }} // 변수값에 인자를 더한다.
{{ first|add:second }}
템플릿 태그
{% tag %}
형태, 텍스트 결과물을 만들거나, 템플릿 로직을 제어하기도 하며, 외부 파일을 로딩하기도 한다.
{% for %} 태그
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>
- for 태그에 사용되는 변수들
- forloop.counter: 현재까지 루프를 실행한 루프 카운트(1부터)
- forloop.counter0: 현재까지 루프를 실행한 루프 카운트(0부터)
- forloop.revcounter: 루프 끝에서 현재가 몇 번째인지 카운트(1부터)
- forloop.revcounter0: 루프 끝에서 현재가 몇 번째인지 카운트(0부터)
- forloop.first: 루프에서 첫 번째 실행이면 True 반환
- forloop.last: 루프에서 마지막 실행이면 True 반환
- forloop.parentloop: 중첩된 루프에서 현재 루프의 상위 루프를 의미함
{% if %} 태그
{% if athlete_list %}
Number of athletes: {{ athlete_list|length }}
{% elif athlete_in_locker_room_list %}
Athletes should be out of the locker room soon!
{% else %}
No athletes.
{% endif %}
어렵지 않으니 설명은 패스~!
다음과 같이 {% if %} 태그에 필터와 연산자를 사용할 수 있다.
{% if athlete_list|length > 1 %}
그리고 다음과 같은 boolean 연산자를 사용할 수 있다.
and, or, not, and not, ==, !=, <, >, <=, >=, in, not in
{% csrf_token %} 태그
<form action="." method="post">
{% csrf_token %}
- CSRF 토큰 값이 유출될 수 있으므로, 외부 URL 로 보내는
{% url %} 태그
{% url 'namespace:view-name' arg1 arg2 %}
- 소스에 URL을 하드 코딩하는 것을 방지한다.
{% with %} 태그
{% with total=business.employees.count %}
{{ total }} people works at business
{% endwith %}
- 특정 값을 변수에 저장해 둔다.
- 변수는 with~endwith 내에서만 유효하다.
{% load %} 태그
{% load somelibrary package.otherlibrary %}
- 사용자 정의 태그 및 필터를 로딩한다.
- 위 예제는 somelibrary.py 파일 및 package/otherlibrary.py 파일에 정의된 사용자 정의 태그 및 필터를 로딩한다.
템플릿 주석
한 줄 주석
{# greeting #}hello
{# {% if foo %}bar{% else %} #}
여러 줄 주석
{# comment "Optional note" #}
<p>Commented out thext here</p>
{# endcomment #}
HTML 이스케이프
Django는 기본적으로 HTML에 사용되는 예약 문자들을 아래와 같이 예약 의미를 제거한 문자로 변경해준다.
< (less than) 문자는 <
> (greater than) 문자는 >
' (single quote) 문자는 '
" (double quote) 문자는 "
& (ampersand) 문자는 &
Django 에서 HTML 이스케이프를 방지하는 방법은 두가지가 존재한다.
safe 필터
This will not be escaped: {{ data|safe }}
{% autoescape %} 태그
{% autoescape off %}
Hello {{ name }}
{% endautoescape %}
템플릿 상속
템플릿 코드의 재사용과 일관성 있는 사이트의 룩앤필을 구성할 수 있게 해준다.
- 부모 템플릿은 뼈대를 만들고,
{% block %}
태그를 통해 상속해줄 부분을 지정한다. - 자식 템플릿은 부모 템플릿의 뼈대를 그대로 사용하고
{% block %}
부분만 채워준다.
부모 템플릿
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheets" href="style.css" />
<title>{% block title %}My amazing site{% endblock %}</title>
</head>
<body>
<div id="sidebar">
{% block sidebar %}
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog">Blog</a></li>
</ul>
{% endblock %}
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
<body>
</html>
자식 템플릿
{% extends "polls/base.html" %}
{% block title %}My amazing blog{% endblock %}
{% block content %}
{% for entry in blog_entries %}
<h2>{{ entry.title }}</h2>
<p>{{ entry.body }}</p>
{% endfor %}
{% endblock %}
위의 템플릿이 브라우저에 렌더링된 결과는 아래와 같다.
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheets" href="style.css" />
<title>My amazing blog</title>
</head>
<body>
<div id="sidebar">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog">Blog</a></li>
</ul>
</div>
<div id="content">
<h2>Entry one</h2>
<p>This is my first entry.</p>
<h2>Entry two</h2>
<p>This is my second entry.</p>
</div>
<body>
</html>
템플릿 상속 정의시 유의할 사항
{% extends %}
태그는 사용하는 태그 중 가장 먼저 나와야 한다.- 템플릿의 공통 사항을 가능한 많이 뽑아서 1단계 부모 템플릿에
{% block %}
태그가 많아지도록 한다. - 부모 템플릿의
{% block %}
태그를 그대로 자식 템플릿에서 사용하려면{{ block.super }}
변수를 사용한다. - 가독성을 높이기 위해
{% endblock content %}
처럼 블록명을 기입할 수 있다.