Django 템플릿 시스템: 변수, 필터, 태그 완벽 가이드

1. Django 템플릿 사용의 두 가지 방법


# 방법 1: render() 함수 사용
return render(request, 'time.html', context={'current_date': str(now), 'title': 'Hello Django'})

# 방법 2: 수동 템플릿 렌더링 (페이지 정적화에 유용)
from django.shortcuts import render, HttpResponse
from django.template import Template, Context
import datetime

now = datetime.datetime.now()
from myproject import settings
import os
file_path = os.path.join(settings.BASE_DIR, 'templates', 'time.html')
file_content = open(file_path, 'r', encoding='utf-8').read()
template = Template(file_content)
context = Context({'current_date': str(now), 'title': 'Hello Django'})
rendered_html = template.render(context)  # 렌더링된 문자열
# 렌더링 결과를 파일로 저장하여 정적 파일로 제공 가능 (동적/정적 전환 로직 구현)
return HttpResponse(rendered_html)

2. 템플릿 문법: 변수


# views.py
def index(request):
    number = 10
    text = 'Hello World'
    flag = True
    items = [1, 2, 43]
    info = {'name': 'Alice', 'age': 25}
    
    def my_function():
        return 'Function result here'
    
    class User():
        def __init__(self, name):
            self.name = name
        
        def get_name(self):
            return self.name
    
    user = User('Alice')
    
    # locals()를 사용하여 모든 지역 변수를 템플릿 컨텍스트로 전달
    return render(request, 'index.html', locals())

# index.html
<html>
<head>
    <meta charset="UTF-8">
    <title>{{ text }}</title>
</head>
<body>
<h1>템플릿 변수 문법</h1>
<p>숫자: {{ number }}</p>
<p>문자열: {{ text }}</p>
<p>불리언: {{ flag }}</p>
<p>리스트: {{ items }}</p>
<p>딕셔너리: {{ info }}</p>
<p>함수: {{ my_function }}</p>
<p>객체: {{ user }}</p>
</body>
</html>

3. 템플릿 문법: 점(.) 연산자를 통한 깊은 조회


# views.py
def index(request):
    number = 10
    text = 'Hello World'
    flag = True
    items = [1, 2, 43, {'name': 'Bob'}]
    info = {'name': 'Alice', 'age': 25}
    
    def my_function():
        return 'Function result'
    
    class User():
        def __init__(self, name):
            self.name = name
        
        def get_name(self):
            return self.name
    
    user = User('Alice')
    
    raw_link = '<a href="https://example.com">Click Me</a>'
    safe_link = mark_safe(raw_link)
    
    raw_input = '<p>Username: <input type="text" name="user"></p>'
    safe_input = mark_safe(raw_input)
    
    raw_script = '''
    <script>
    alert('XSS test');
    </script>
    '''
    safe_script = mark_safe(raw_script)
    
    return render(request, 'index.html', locals())

# index.html
<h2>점(.) 연산자를 통한 깊은 조회</h2>
<p>리스트 첫 번째 요소: {{ items.1 }}</p>
<p>딕셔너리의 name 값: {{ info.name }}</p>
<p>리스트 네 번째 요소의 name 값: {{ items.3.name }}</p>
<p>함수 실행: {{ my_function }}</p>
<p>클래스 메서드 호출: {{ user.get_name }}</p>
<p>클래스 속성 접근: {{ user.name }}</p>
<hr>
<p>안전하지 않은 링크 문자열: {{ raw_link }}</p>
<p>안전한 링크 (HTML 렌더링): {{ safe_link }}</p>
<p>안전하지 않은 input: {{ raw_input }}</p>
<p>안전한 input: {{ safe_input }}</p>
<p>안전하지 않은 스크립트: {{ raw_script }}</p>
{{ safe_script }}

4. 내장 필터


1. default
# 변수가 false이거나 비어있으면 기본값 사용
{{ value|default:"nothing" }}

2. length
# 문자열 또는 리스트의 길이 반환
{{ value|length }}

3. filesizeformat
# 파일 크기를 사람이 읽기 쉬운 형식으로 변환
{{ value|filesizeformat }}

4. date
# 날짜/시간 형식 변환
{{ value|date:"Y-m-d" }}

5. slice
# 문자열 슬라이싱
{{ value|slice:"2:-1" }}

6. truncatechars
# 문자열을 지정된 문자 수로 자르고 '...' 추가
{{ value|truncatechars:9 }}

7. safe
# HTML 태그 자동 이스케이프 방지
value="<a href=''>Click</a>"
{{ value|safe }}

실제 사용 예시


<p>기본값 필터: {{ number|default:'No value' }}</p>
<p>길이 필터: {{ items|length }}</p>
<p>길이 필터 (딕셔너리): {{ info|length }}</p>
<p>파일 크기 포맷: {{ number|filesizeformat }}</p>
<p>슬라이스 필터: {{ text|slice:"7:11" }}</p>
<p>문자 자르기 (truncatechars): {{ text|truncatechars:'30' }}</p>
<p>단어 자르기 (truncatewords): {{ text|truncatewords:'2' }}</p>
<p>날짜 포맷: {{ current_time|date:'Y-m-d H:i:s' }}</p>
<p>안전한 HTML 출력: {{ raw_link|safe }}</p>

{# add: 값 더하기 #}
<p>{{ "10"|add:"-2" }}</p>

{# upper/lower: 대소문자 변환 #}
<p>{{ text|upper }}</p>
<p>{{ 'EXAMPLE'|lower }}</p>

5. 템플릿 태그

for 루프 활용


{# forloop 속성들 #}
{% for item in items %}
    {{ forloop.counter }}  {# 1부터 시작하는 인덱스 #}
    {{ forloop.counter0 }} {# 0부터 시작하는 인덱스 #}
    {{ forloop.revcounter }} {# 1부터 시작하는 역순 인덱스 #}
    {{ forloop.revcounter0 }} {# 0부터 시작하는 역순 인덱스 #}
    {{ forloop.first }} {# 첫 번째 반복인지 확인 #}
    {{ forloop.last }} {# 마지막 반복인지 확인 #}
{% endfor %}

{# 중첩 루프에서 parentloop 사용 #}
{% for outer_list in data %}
    {% for item in outer_list %}
        {{ forloop.parentloop.counter }}
        {{ forloop.counter }}
    {% endfor %}
{% endfor %}

for ... empty 태그


{% for person in person_list %}
    <p>{{ person.name }}</p>
{% empty %}
    <p>No persons found.</p>
{% endfor %}

if 태그


{% if score > 100 or score < 0 %}
    <p>Invalid score</p>
{% elif score > 80 and score < 100 %}
    <p>Excellent</p>
{% else %}
    <p>Average</p>
{% endif %}

{# 지원 연산자: and, or, ==, >, <, !=, <=, >=, in, not in, is, is not #}
{# 주의: 연속 비교는 지원하지 않음 (예: a > b > c) #}

with 태그


{# 복잡한 변수를 간단한 이름으로 캐싱 #}
{% with total=company.employees.count %}
    {{ total }} {# with 블록 내에서만 사용 가능 #}
{% endwith %}

{% with company.employees.count as total %}
    {{ total }}
{% endwith %}

csrf_token 태그


{# POST 폼에서 CSRF 보호를 위해 필수 #}
<form method="post">
    {% csrf_token %}
    <input type="text" name="data">
    <button type="submit">Submit</button>
</form>

템플릿 포함과 상속


{# 템플릿 포함 (include) #}
{% include 'navbar.html' %}
{% include 'footer.html' %}

{# 템플릿 상속 (extends) #}
{% extends 'base.html' %}

{% block content %}
    {{ block.super }} {# 부모 블록 내용 유지 #}
    <h2>Sub page content here</h2>
{% endblock %}

사용자 정의 필터와 태그


# 1. 앱 폴더에 templatetags 패키지 생성
# 2. templatetags 폴더에 Python 파일 생성 (예: custom_tags.py)
# 3. settings.py의 INSTALLED_APPS에 앱 등록

# custom_tags.py
from django import template
register = template.Library()

# 사용자 정의 필터
@register.filter
def custom_filter(value, arg=''):
    return value + ' ' + arg

# 사용자 정의 태그
@register.simple_tag
def custom_tag(v1, v2, v3):
    return f'{v1} + {v2} + {v3}'

# inclusion_tag
@register.inclusion_tag('list_component.html')
def render_list(count):
    data = ['Item {}'.format(i) for i in range(count)]
    return {'data': data}

# HTML 템플릿에서 사용
{% load custom_tags %}
{{ value|custom_filter:'argument' }}
{% custom_tag 'A' 'B' 'C' %}
{% render_list 5 %}

inclusion_tag 상세 사용법


# custom_tags.py
@register.inclusion_tag('menu.html')
def sidebar(menu_count):
    menu_items = {i: 'Page {}'.format(i) for i in range(menu_count)}
    return {'menu_items': menu_items}

# menu.html
{% for key, value in menu_items.items %}
    <p>Key: {{ key }}, Value: {{ value }}</p>
{% endfor %}

# 사용 템플릿
{% load custom_tags %}
<div class="sidebar">
    {% sidebar 10 %}
</div>

태그: Django 템플릿 Django 템플릿 태그 템플릿 필터 inclusion_tag

5월 29일 20:31에 게시됨