파이썬 Flask 사용법 2 (Jinja2 템플릿)
이전 글에서 파이썬 Flask(플라스크) 초간단 사용법을 익혀봤다. 그 글에서는 클라이언트에게 돌려줄 웹 페이지로 단순한 HTML 형식의 문자열을 작성하는 예시를 사용했다. 물론 이렇게 해도 웹페이지가 잘 나타나긴 하지만 만약 제대로 된 웹 사이트, 즉 애플리케이션이라는 걸 만들고자 한다면 모든 페이지마다 HTML 파일을 각각 작성할 게 아니라 일관된 구조와 기능을 가진 템플릿(template)을 활용해야 한다.
Flask에서는 Jinja2라는 템플릿 엔진을 사용해서 애플리케이션 내 변수와 반복문, 조건문 등을 포함하는 HTML 파일을 렌더링할 수 있다. 그래서 이번 글에서는 Jinja2 사용법과 함께 템플릿 내에서 변수, 조건문/반복문 사용법에 대해 익혀보려 한다.
템플릿 렌더링해서 URL에 연결하기
일단 프로젝트 폴더 내에는 app.py라는 파일을 아래와 같이 작성해보자.
1
2
3
4
5
6
7
8
9
10
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template("index.html")
if __name__ == '__main__':
app.run(debug=True)
그리고 프로젝트 폴더 내에 templates라는 폴더를 생성하고 (폴더 이름은 반드시 templates여야 한다.)
그 안에 index.html이라는 파일을 생성하고 아래와 같이 넣어보자.
1
2
3
4
5
6
<!DOCTYPE html>
<html>
<body>
<h1>메인 화면</h1>
</body>
</html>
그리고 app.py를 실행하면 Running on http://127.0.0.1:5000/라는 메시지가 뜨는데 (로컬 환경에서 5000번 포트를 사용한다는 뜻) 웹 브라우저로 여기 들어가보면 된다.
그러면 첫 화면이 index.html을 띄워줄 거다. @app.route('/')
에 바인딩 된 함수가 render_template("index.html")
이라고 되어 있기 때문에 해당 문서를 렌더링해서 반환하는 거다. Flask 참 쉽다.
템플릿에서 변수 사용하기 (filter 기능 활용)
템플릿 내에서 변수를 사용하려면 render_template()
괄호 안에 렌더링 할 HTML 파일 이름에 이어 변수명을 키워드 인수를 추가해주면 된다. 둘 이상의 변수를 추가하려면 쉼표로 구분하면 그만이다.
실제로 템플릿에서 이 변수를 사용할 때는 {{ 변수명 }}
과 같은 식으로 불러와서 쓰면 된다.
그리고 이 변수를 템플릿 내에서 파이썬 함수처럼 filter 기능으로 처리하는 방법도 있다. {{ 변수명 | 필터 }}
와 같은 식으로 써주면 된다. (Jinja2 공식 문서 참고)
템플릿에서 if 조건문 사용하기
if 조건문은 이런 형식으로 바로 써줄 수 있다.
1
2
3
{% if template_variable == "Hello" %}
<p>{{ template_variable }}, World!</p>
{% endif %}
elif와 else도 파이썬에서 직접 사용하는 것과 같은 문법으로 사용할 수 있다.
1
2
3
4
5
6
7
{% if template_variable < 20 %}
<p>{{ template_variable }}은 20보다 작다.</p>
{% elif template_variable > 20 %}
<p>{{ template_variable }}은 20보다 크다.</p>
{% else %}
<p>{{ template_variable }}은 20이다.</p>
{% endif %}
템플릿에서 for 반복문 사용하기
for 반복문도 마찬가지다.
1
2
3
4
5
<ul>
{% for x in range(10) %}
<li>{{ x }}</li>
{% endfor%}
</ul>
딕셔너리도 당연히 활용 가능하다.
1
2
3
4
5
<ul>
{% for key, value in template_dict.items() %}
<li>{{ key }} : {{ value }}</li>
{% endfor%}
</ul>
dictsort
필터를 사용할 때는 (뒤에 굳이 .items()
를 붙여주지 말고) 이런 식으로 써야 하더라. 이것 때문에 삽질 좀 했다.
1
2
3
4
5
<ul>
{% for key, value in template_dict | dictsort %}
<li>{{ key }} : {{ value }}</li>
{% endfor%}
</ul>
템플릿 상속 (Inheritance)
웹 사이트 레이아웃의 일관성을 유지하거나, header와 footer를 여러곳에 사용하기 위해서는 템플릿 상속 기능을 사용하면 된다.
- 부모문서를 만들고, 자식문서가 들어갈 부분에
{% block content %}
{% endblock %}
라고 작성한다. - 자식문서 윗부분에
{% extends 부모문서이름 %}
라고 명시한 후{% block content %}
와{% endblock %}
사이에 내용을 작성한다.
예를 들어 base.html이라는 부모문서를 이렇게 작성하고
1
2
3
4
5
6
7
8
<html>
<head>
<title>내 웹사이트</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
index.html이라는 이름으로 자식 문서를 만들면, 그 자식문서에는 이렇게 적어주면 되겠다.
1
2
3
4
5
6
{% extends "base.html" %}
{% block content %}
<p>자식문서에 포함될 내용</p>
{% endblock %}
실제로 index.html이라는 문서를 render_template("index.html")
와 같이 렌더링 해서 확인하면 아래와 같이 구성이 된다는 걸 알 수 있다.
1
2
3
4
5
6
7
8
<html>
<head>
<title>내 웹사이트</title>
</head>
<body>
<p>자식문서에 포함될 내용</p>
</body>
</html>
Flask 템플릿 상속 쉽다.
이제 지금까지 학습한 내용을 한 방에 예시로 익혀보자.
코드 예시 – 종합 요약
Flask 템플릿 내에서 변수 필터링 및 조건문/반복문, 템플릿 상속을 테스트하기 위한 간단한 예시.
학생들의 정보와 시험 성적을 딕셔너리로 만들어놓은 후, 메인 페이지에서 이름을 확인하면 해당 학생의 성적이 리스트로 출력되는 페이지를 만들어보았다.
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from flask import Flask, render_template
app = Flask(__name__)
student_data = {
1: {"name": "슈퍼맨", "score": {"국어": 90, "수학": 65}},
2: {"name": "배트맨", "score": {"국어": 75, "영어": 80, "수학": 75}}
}
@app.route('/')
def index():
return render_template("index.html",
template_students = student_data)
@app.route("/student/<int:id>")
def student(id):
return render_template("student.html",
template_name=student_data[id]["name"],
template_score=student_data[id]["score"])
if __name__ == '__main__':
app.run(debug=True)
base.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>시험성적 확인 사이트</title>
</head>
<body>
<div>
<a href="/">메인화면 바로가기</a>
</div>
{% block content %}{% endblock %}
</body>
</html>
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{% extends "base.html" %}
{% block content %}
<h1>시험 성적 확인하기</h1>
<p>이름을 클릭하세요.</p>
<ul>
{% for key, value in template_students | dictsort %}
<li><a href="/student/{{ key }}">{{ value["name"] }}</a></li>
{% endfor%}
</ul>
{% endblock %}
student.html
{% extends "base.html" %}
{% block content %}
<h2>{{ template_name }} 님의 성적</h2>
<ul>
{% for key, value in template_score.items() %}
<li>{{ key }} : {{ value }}</li>
{% endfor%}
</ul>
{% endblock %}
일단 Flask 템플릿 사용법은 여기까지.