본문 바로가기
카테고리 없음

[tutorial] Jinja2 : Python template language

by 째깍단 2024. 2. 21.

** 2.x.x의 공식문서와 3.x.x의 공식문서 및 위키독스를 참고하였음

 

공식문서 :  https://jinja.palletsprojects.com/en/3.1.x/intro/

 

 

 

Jinja2는 Python에서 사용되는 템플릿 엔진으로, 현대적이고 디자이너 친화적인 템플릿 언어이다.

 

Django template에서 영감을 받았으며,

Flask같은 웹 프레임워크에서 HTML 템플릿을 렌더링하는 데 주로 사용되지만 여러 텍스트 파일을 생성하는 데도 사용할 수 있다.

 

Django template처럼 for문, if문을 활용해 동적인 콘텐츠를 생성할 수 있으며, 변수를 치환하는 표현식을 이용한다.

 

Jinja2는 어플리케이션 로직이 Python 로직에 모두 속하게 하는 것과

디자이너의 작업이 언어로 인해 제한되지 않도록 하는 것에 중점을 두어 디자인되었다.

 

 


 

 

 

설치 방법 :

pip install Jinja2

 

 

- Jinja2를 설치하면 MarkupSafe가 함께 설치되는데, 템플릿 렌더링 시 신뢰할 수 없는 입력을 방지해주는 라이브러리이다.

 

- optional로 Babel을 함께 설치할 수 있는데, 템플릿 번역 지원 기능을 제공한다고 한다.

 

 

 


 

 

Jinja API(템플릿 인터페이스 활용) : https://jinja.palletsprojects.com/en/3.1.x/api/

 

 

 

Jinja2의 핵심 모듈에는 Template, Environment, Package Loader가 있다.

 

 

 

Template 클래스 생성자를 사용하면, 문자열로 템플릿을 만들더라도 Template 자동으로 템플릿을 생성해준다.

 

 

Environment는 템플릿 로드 환경을 제공하는데, 

대부분의 어플리케이션은 어플리케이션 초기화 하나의 Environment 개체를 생성하고, 이를 사용하는 템플릿을 로드하게 된다.

몇몇 경우에, 멀티 환경에서 다른 구성의 템플릿을 유용하게 로드하여 사용할 있다.

 

 

Package Loader를 사용해 Jinja2를 구성하여 어플리케이션의 템플릿으로 로드하는 것이 가장 간단한 방법이다.

 

from jinja2 import Environment, PackageLoader, select_autoescape

env = Environment(
    loader=PackageLoader("yourapp"),
    autoescape=select_autoescape()
)

 

위 코드가 'yourapp'에 있는 templates 폴더 내의 템플릿들을 찾아 로더와 함께 템플릿 환경을 생성해줄 것이다.

HTML파일에 대한 자동변환도 가능하다.

loader 'yourapp'을 불러오는데에 요구되며, 절대경로를 사용한다.

 

 

 

 

템플릿을 로드하기 위해 Template를 return해주는 get_template()메서드를 사용한다.

template = env.get_template("mytemplate.html")

 

 

 

몇몇 변수를 불러오기 위해 render()메서드를 사용할 수 있다.

print(template.render(the="variables", go="here"))

 

get_template()로 가져온 템플릿에 render()메서드를 사용해 특정 변수 불러오기가 가능하다.

 

 

 

단순 문자열을 사용하는 것보다

Template Environment.from_string() 통해 template loader 사용하는 것이 여러 장점이 있고, 상속도 가능하다고 한다.

 

 

 

 


 

 

 

Template Desinger 문서(템플릿 언어 활용) : https://jinja.palletsprojects.com/en/3.1.x/templates/

 

 

기본적으로 중괄호와 여러 구분기호를 사용하지만 개발자가 구문 구성을 변경할 수 있다.

{% foo %} <% foo %>

 

 

 

기본 Jinja 구분 기호는 다음과 같이 구성됩니다.

  • {% ... %} for문, if문 등
  • {{ ... }}템플릿 출력으로 인쇄할 표현식
  • {# ... #} 템플릿 출력에 포함되지 않은 설명의 경우

영감을 받은 만큼 Django 템플릿 언어와 흡사하다

 

 

 

 

 

라인문과 주석도 가능하다.

 

line_statement_prefix #을 사용해서 for문을 이용할 수 있음!

아래 두 예시는 동등한 결과를 가져온다.

 

<ul>
# for item in seq   ## : 콜론을 붙일 수 있다.
    <li>{{ item }}</li>
# endfor            ## endfor seq 가독성을 위해 endfor 해당하는 개체를 명시할 수 있다.
</ul>

<ul>
{% for item in seq %}
    <li>{{ item }}</li>
{% endfor %}
</ul>

 

 가독성을 위해 for, if, elif문 뒤에 콜론을 붙일 수 있다.

 

 

 

 

또한 ## ignore되므로 줄바꾸기 기호를 제외하고 끝까지의 모든 내용을 무시한다.

 

<ul>
# for item in seq   ## 주석: seq는 ~~한 객체 
...

 

 

 

 

이외의 것은 공부하면서 상단의 공식 문서를 참고할 것!

 

 

 

 


 

 

아래는 간단 예제

 

 

telegram봇에 원하는 형식으로 메세지를 보내기 위해 활용하였는데, 어렵지 않게 원하는 방식으로 동적인 text를 렌더링할 수 있다.

 

 

 

참고용 디렉토리 구조

 

 

 

변수를 넣어 test.html 파일을 생성하였다.

<html>
  <head>
    <title>Hi, It's Jinja. {{title}}</title>
  </head>
  <body>
    <h1>
      Hello, {{ name }}
    </h1>
    <h2>
      {{ heading }}
    </h2>
    <h3>
      {{ content }}
    </h3>
  </body>
</html>

 

 

 

 

FileSystemLoader로 해당 파일의 경로를 적어 test.html파일을 불러온 후 Environment에 넣어 환경을 설정해준다.

from jinja2 import Environment, FileSystemLoader

# 템플릿에 전달할 데이터

data = {
    'title': 'Jinja2 Test',
    'heading': 'Jinja2 템플릿 엔진',
    'content': '이것은 Jinja2 테스트 예제입니다.',
    'name': 'python_bot'
}

# 템플릿 파일이 있는 디렉토리 설정
file_loader = FileSystemLoader('tutorials/Jinja/templates')
jinja_env = Environment(loader=file_loader)


# telegram bot에 넣어주기 위해 함수로 작성
def load_data():

    # 템플릿 파일 로드
    template = jinja_env.get_template('test.html')

    # 템플릿 랜더링
    output = template.render(data)

    return output

 

 

 

 

study.py에 작성되어있는 기본 telegram bot의 text에 메시지를 전송할 수 있도록 함수를 입력해주었다.

from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler
from telegram import Update
import logging
import asyncio
import telegram
import dotenv


# 다른 디렉토리에서 함수를 가져오기 위한 설정
import sys
import os
sys.path.append(os.path.dirname(os.path.abspath(os.path.dirname(os.path.abspath(os.path.dirname(__file__))))))

from tutorials.Jinja.load_template import load_data



async def main():
    BOT_TOKEN = dotenv.os.getenv("TELEGRAM_BOT_TOKEN")
    CHAT_ID = dotenv.os.getenv("TELEGRAM_CHAT_ID")

    bot = telegram.Bot(BOT_TOKEN)

    print()
    async with bot:
    	# text에 함수를 입력해준다.
        await bot.send_message(text=load_data(), chat_id=CHAT_ID)


if __name__ == '__main__':
    dotenv.read_dotenv() # .env에 있는 token과 chat_id를 불러옴
    asyncio.run(main()) # 비동기로 bot 실행

 

 

 

 

템플릿 언어와 함께 보내진 메시지 확인!

 

 

실행결과 bot에 텍스트로 보내지다보니,

특정한 템플릿이 필요하지 않다면 템플릿 언어는 빼고 text만 작성하여 전송할 수 있을 것 같다.

 

 

템플릿 형식으로 보내는 방법 추가 연구 필요.