본문 바로가기

Python

Python - Jinja2(템플릿 엔진)

템플릿 엔진(Template Engine) 이란?

템플릿 엔진은 정적인 HTML에 동적인 데이터를 결합하여 웹 페이지를 생성합니다. 템플릿 파일에 데이터를 삽입하여 동적인 HTML을 생성합니다.

Jinja2 란

Python에서 가장 많이 사용되는 템플릿 엔진입니다. 마이크로 웹 프레임워크인 Flask에서 채택되어 사용되고 있습니다.

Jinja2 설치

pip install Jinja2

사용 예시

기본 예시:

from jinja2 import Template

# 템플릿
template = Template('Hello, {{ name }}!')

# 데이터
data = {'name': 'John'}

# 렌더링: 템플릿에 데이터를 삽입하여 최종 HTML 생성
result = template.render(data)
print(result)  # 출력: Hello, John!

HTML:

from jinja2 import Template

template_str = """
<h1>{{ title }}</h1>
<p>{{ description }}</p>
"""
template = Template(template_str)

data = {
    "title": "Welcome to Jinja2",
    "description": "This is a simple Jinja2 example."
}

# 렌더링: 템플릿에 데이터를 삽입하여 최종 HTML 생성
result = template.render(data)
print(result)

HTML 파일(HTML 파일을 사용할 경우):

hello.html - 'templates' 디렉토리에 저장:

<!DOCTYPE html>
<html>
<head>
    <title>Jinja2 Demo</title>
</head>
<body>
    <h1>Hello, {{ name }}!</h1>
</body>
</html>

hello.py:

from jinja2 import Environment, FileSystemLoader

# 템플릿 파일이 있는 디렉토리 경로을 인자로 전달하여 Environment 객체 생성
env = Environment(loader=FileSystemLoader('templates'))

# Environment 객체로 부터 템플릿 로딩
template = env.get_template('hello.html')

# 데이터
data = {'name': 'Jinja2'}

# 렌더링: 템플릿에 데이터를 삽입하여 최종 HTML 생성
rendered_html = template.render(data)

print(rendered_html)

변수

변수를 사용 하기 위해 {{ }} 를 사용합니다.

from jinja2 import Template

template_str = """
<h1>{{ title | upper}}</h1>
<p>{{ description | capitalize}}</p>
"""
template = Template(template_str)

data = {
    "title": "Welcome to Jinja2",
    "description": "This is a simple Jinja2 example."
}

result = template.render(data)
print(result)

딕셔너리 타입의 변수

data = {
    "user": {
        "name": "John",
        "age": 30
    }
}

template_str = "{{ user.name }} is {{ user.age }} years old."
template = Template(template_str)
result = template.render(data)
print(result)  # 출력: John is 30 years old.

변수 연산

data = {
    "variable": 10
}

template_str = "{{ variable + 1 }}"
template = Template(template_str)
result = template.render(data)
print(result)  # 출력: 11
data = {
    "variable": "10"
}

template_str = "{{ variable + '1' }}"
template = Template(template_str)
result = template.render(data)
print(result)  # 출력: 101

변수 필터링

from jinja2 import Template

template_str = """
<h1>{{ title | upper}}</h1>
<p>{{ description | capitalize}}</p>
"""
template = Template(template_str)

data = {
    "title": " Welcome to Jinja2 ",
    "description": "This is a simple Jinja2 example."
}

result = template.render(data)
print(result)
  • upper: 대문자로 변환
  • capitalize: 첫 글자만 대문자로 변환

이 외에 다양한 필터가 있습니다.

  • lower: 소문자로 변환
  • title: 각 단어의 첫 글자를 대문자로 변환
  • trim: 문자열 앞뒤 공백 제거
  • replace: 문자열 치환
  • ...

주석

{# ... #} 를 사용하여 주석을 작성할 수 있습니다. 랜더링 결과에 포함되지 않습니다.

from jinja2 import Template

template_str = """
<h1>{{ title }}</h1>
{# This is a comment #}
<p>{{ description }}</p>
"""
template = Template(template_str)

data = {
    "title": "Welcome to Jinja2",
    "description": "This is a simple Jinja2 example."
}

result = template.render(data)
print(result)

제어문

조건문

{% if ... %} ... {% endif %} 를 사용하여 조건문을 작성할 수 있습니다.

from jinja2 import Template

template_str = """
{% if user.age >= 18 %}
    <p>{{ user.name }} is an adult.</p>
{% else %}
    <p>{{ user.name }} is a minor.</p>
{% endif %}
"""

template = Template(template_str)

data = {
    "user": {
        "name": "John",
        "age": 30
    }
}

result = template.render(data)
print(result)

반복문

from jinja2 import Template

template_str = """
<ul>
{% for item in items %}
    <li>{{ item }}</li>
{% endfor %}
</ul>
"""

template = Template(template_str)

data = {
    "items": ["Apple", "Banana", "Cherry"]
}

result = template.render(data)
print(result)

매크로(Macro)

매크로는 템플릿에서 사용할 수 있는 함수를 정의할 수 있습니다.

 

from jinja2 import Template

template_str = """
{% macro input(name, value='', type='text') %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}

{{
    input('username')
}}
{{
    input('password', type='password')
}}
"""

template = Template(template_str)
result = template.render()
print(result)
  • macro 키워드를 사용하여 매크로를 정의합니다.
  • input 매크로는 name, value, type 세 개의 인자를 받습니다.
  • input 매크로를 호출할 때 인자를 전달합니다.

다른 파일의 매크로 가져오기

macro.html - 'templates' 디렉토리에 저장:

{% macro input(name, value='', type='text') %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
{% endmacro %'}'

macro_test.html - 'templates' 디렉토리에 저장:

{% from 'macro.html' import input %}

{{
    input('username')
}}
{{
    input('password', type='password')
}}

macro_test.py:

from jinja2 import Environment, FileSystemLoader

env = Environment(loader=FileSystemLoader('templates'))
template = env.get_template('macro_test.html')

result = template.render()
print(result)

템플릿 상속

템플릿 상속은 기본 템플릿(골격: 머리글, 바닥글, 메뉴, ...)을 만들고 하위 템플릿에서 기본 템플릿을 상속받아 해당 페이지의 특정한 콘텐츠만 변경할 수 있습니다.

base.html - 'templates' 디렉토리에 저장:

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}My Website{% endblock %}</title>
</head>
<body>
    <header>
        <h1>My Website</h1>
        <nav>
            <!-- Navigation links -->
        </nav>
    </header>

    <main>
        {% block content %}
        <!-- Default content goes here if not overridden -->
        {% endblock %}
    </main>

    <footer>
        <!-- Footer content -->
    </footer>
</body>
</html>

home.html - 'templates' 디렉토리에 저장:

{% extends 'base.html' %}

{% block title %}Home{% endblock %}

{% block content %}
    <h2>Welcome to My Website</h2>
    <p>This is the home page.</p>
{% endblock %}

about.html - 'templates' 디렉토리에 저장:

{% extends 'base.html' %}

{% block title %}About{% endblock %}

{% block content %}
    <h2>About Us</h2>
    <p>This is the about page.</p>
{% endblock %}

home.py:

from jinja2 import Environment, FileSystemLoader

env = Environment(loader=FileSystemLoader('templates'))
template = env.get_template('home.html')

result = template.render()
print(result)

template = env.get_template('about.html')
result = template.render()
print(result)

템플릿 include

include 키워드를 사용하여 다른 템플릿을 포함할 수 있습니다.

header.html - 'templates' 디렉토리에 저장:

<header>
    <h1>My Website</h1>
    <nav>
        <!-- Navigation links -->
    </nav>
</header>

footer.html - 'templates' 디렉토리에 저장:

<footer>
    <!-- Footer content -->
</footer>

base.html - 'templates' 디렉토리에 저장:

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}My Website{% endblock %}</title>
</head>
<body>
    {% include 'header.html' %}

    <main>
        {% block content %}
        <!-- Default content goes here if not overridden -->
        {% endblock %}
    </main>

    {% include 'footer.html' %}
</body>
</html>

home.py:

from jinja2 import Environment, FileSystemLoader

env = Environment(loader=FileSystemLoader('templates'))
template = env.get_template('base.html')

result = template.render()
print(result)

Flask 에서 Jinja2 사용

Flask 설치

pip install Flask

templates/index.html:

<!DOCTYPE html>
<html>
<head>
    <title>Flask with Jinja2</title>
</head>
<body>
    <h1>{{ message }}</h1>
</body>
</html>

app.py:

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def index():
    message = "Hello, Flask!"
    return render_template("index.html", message=message)

if __name__ == "__main__":
    app.run()    

app.py 실행:

python app.py

브라우저에서 http://localhost:5000 접속:

<!DOCTYPE html>
<html>
<head>
    <title>Flask with Jinja2</title>
</head>
<body>
    <h1>Hello, Flask!</h1>
</body>
</html>

FastAPI 에서 Jinja2 사용

FastAPI 설치

pip install fastapi uvicorn

templates/index.html:

<!DOCTYPE html>
<html>
<head>
    <title>FastAPI with Jinja2</title>
</head>
<body>
    <h1>{{ message }}</h1>
</body>
</html>

main.py:

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates

app = FastAPI()

templates = Jinja2Templates(directory="templates")

@app.get("/", response_class=HTMLResponse)
async def read_item(request: Request):
    message = "Hello, FastAPI!"
    return templates.TemplateResponse("index.html", {"request": request, "message": message})

main.py 실행:

uvicorn main:app --reload

브라우저에서 http://localhost:8000 접속:

<!DOCTYPE html>
<html>
<head>
    <title>FastAPI with Jinja2</title>
</head>
<body>
    <h1>Hello, FastAPI!</h1>
</body>
</html>

'Python' 카테고리의 다른 글

Python - SQLAlchemy  (0) 2024.04.02
Python - 공공데이터 포털 Open API 사용하기  (0) 2024.03.27
Python - JSON(JavaScript Object Notation)  (0) 2024.03.23
Python - 가상환경(venv)  (0) 2024.03.23
Python - 비밀번호 해싱  (0) 2024.03.23