시작에 앞서
해당 내용은 <가장 빠른 풀스택을 위한 Flask & FastAPI>, Dave Lee 지음. BJ Public 출판.
내용을 토대로 작성되었습니다. 보다 자세한 사항은 해당 교재를 참고하시기 바랍니다.
템플릿
템플릿: 웹 페이지의 구조나 레이아웃을 미리 정의해 놓은 파일
플라스크에서는 Jinja2(진자2) 라는 템플릿 엔진을 사용하는데, Jinja2는 파이썬 코드를 HTML 파일에 삽입하여 웹페이지를 동적으로 생성할 수 있게 해준다.
Jinja2는 Python에서 사용되는 빠르고 표현력 있는 템플릿 엔진이다. 이 엔진은 템플릿 안에 Python과 유사한 문법을 사용하여 코드를 작성할 수 있게 해준다.
플라스크 애플리케이션 폴더 내에 templates 라는 디렉터리를 생성하고, 이곳에 HTML 파일을 저장한다.
<!DOCTYPE html>
<html>
<head>
<title>Hello</title>
</head>
<body>
<h1>Hello, {{name}}! </h1>
</body>
</html>
▶ HTML 파일에서 {{name}} 부분은 Jinja2의 템플릿 문법이다. 이 위치에 파이썬 변수를 삽입할 수 있다.
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/hello/<name>')
def hello(name):
return render_template('hello.html', name=name)
위 코드는 http://127.0.0.1:5000/hello/[이름] 형태의 URL을 통해 접속하면 Hello, [이름]! 이라는 응답을 준다.
render_template() 함수는 특정 경로에 해당하는 HTML 파일을 전달해주는 함수이다.
변수와 제어문
Jinja2 템플릿 엔진은 단순히 변수를 삽입하는 것뿐만 아니라, 제어문(If, For 등)도 사용할 수 있다.
★ 제어문에 대해 궁금하다면?! [파이썬] 파이썬기초: 제어문 - if문 [파이썬] 파이썬기초: 제어문 - while문 [파이썬] 파이썬기초: 제어문 - for문 |
아래와 같은 방식으로 조건에 따라 다른 내용을 출력할 수 있다.
{% if name %}
<hi>Hello, {{name}}!</h1>
{% else %}
<hi>Hello, World!</h1>
{% endif %}
필터
필터는 변수의 값을 출력하기 전에 처리하여 변형하는 기능을 제공한다.
예. 입력한 문자열을 대문자로 변환, 날짜 형식 변경 등
Jinja2에서는 다양한 내장 필터를 제공하며, 필요에 따라 사용자 정의 필터도 추가할 수 있다.
<p>{{ user_name|capitalize}}</p> <!-- 첫 글자를 대문자로 변환>
-->
<p>{{ story|truncate(100) }}</p> <!-- 문자열을 100자로 제한>
-->
<p>{{ timestamp|date("Y-m-d H:i") }}</p> <!-- 날짜 형식을 지정된 형태로 변환>
-->
[필터 옵션]
- safe: HTML 태그를 이스케이핑 하지 않는다.
- capitalize: 문자열의 첫 글자를 대문자로 만든다
- lower: 문자열을 소문자로 만든다
- upper: 문자열을 대문자로 만든다
- title: 문자열의 각 단어의 첫 글자를 대문자로 만든다
- trim: 문자열의 앞뒤 공백을 제거한다
- striptags: 문자열에서 HTML 태그를 제거한다
- truncate: 문자열을 특정 길이로 줄인다
- date: datetime 객체를 문자열로 포맷한다.
※ 이스케이핑: 어떤 문자가 그것에 부여된 특정한 의미, 기능으로 해석되는 게 아니라 그냥 단순한 문자 하나로 해석되도록 하는 것
반복문
Jinja2에서는 for 반복문을 사용하여 리스트나 딕셔너리 같은 컬렉션의 요소들을 순회하며 출력할 수 있다.
먼저, 단순한 fruits 리스트를 화면에 나열하는 HTML 템플릿을 만들어본다.
templates 디렉터리 안에 fruits_list.html 파일을 생성하고 아래 코드를 입력한다.
<!-- templates/fruits_list.html-->
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset="UTF-8>"
<title>Fruits List</title>
</head>
<body>
<h1>Fruits List</h1>
<ul>
{% for fruit in fruits %}
<li>{{ fruit }}</li>
{% endfor %}
</ul>
</body>
</html>
이제 플라스크 애플리케이션(app.py)에서 fruits_list.html 템플릿을 사용하는 뷰 함수를 만든다.
이 함수에서는 fruits 라는 변수에 과일의 이름이 담긴 리스트를 넣고 템플릿으로 전달한다.
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/fruits')
def show_fruits():
# 테스트할 과일 목록을 넣는다
fruits = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry']
return render_template('fruits_list.html', fruits=fruits)
http://127.0.0.1:5000/fruits 로 접속하면
위에서 정의한 과일 목록이 웹페이지에 나열되어 보인다.
매크로
매크로를 사용하는 것은 파이썬에서 함수를 정의하고 호출하는 것과 아주 유사하다.
웹페이지에서 반복해서 사용되는 HTML 요소들을 매크로로 정의해두면, 여러 곳에서 필요할 때마다 그 매크로를 호출하여 재사용할 수 있다.
플라스크 프로젝트에서 templates 디렉터리 안에 매크로를 포함한 HTML 파일을 저장한다. (macros.html)
<!-- templates/macors.html-->
{% macro display_message(message) %}
<p>{{ message }}</p>
{% endmacro %}
▶ 여기서 정의된 display_message 매크로는 메시지라는 단 하나의 매개변수를 받아서 단순히 <p> 태그 안에 그 메시지를 출력한다.
그리고 templates/messages.html 파일을 만들어 이 매크로를 사용해본다.
<!-- templates/messages.html-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8>"
<title>Simple Message Example</title>
</head>
<body>
{% from "macros.html" import display_message %}
<!-- 매크로 호출-->
{{ display_message('환영합니다! 여기가 우리 사이트입니다.') }}
{{ display_message('주의해 주세요, 에러가 발생했습니다.') }}
{{ display_message('성공! 당신의 작업이 성공적으로 완료되었습니다.')}}
</body>
</html>
▶ {% from "mcros.html" import display_message %} 구문을 통해 macros.html에서 display_message 매크로를 가져와서 사용한다.
마지막으로, 플라스크 애플리케이션에서 이 두 파일을 사용하는 뷰 함수를 만든다.
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/messages')
def show_messages():
return render_template('messages.html')
이제 http://127.0.0.1:5000/messages 로 접속하면
messages.html에 정의된 매크로를 통해 세 가지 타입의 메시지를 표시하는 웹페이지를 볼 수 있다.
이 구조를 사용하면 매크로를 한곳에 모아서 관리할 수 있으며, 다른 HTML 템플릿에서 쉽게 재사용할 수 있다.
이는 코드의 중복을 줄이고 유지보수성을 향상시키는 효과적인 방법이다.
템플릿 상속
템플릿 상속(template inheritance)을 이용하면 기본 레이아웃을 정의한 '부모' 템플릿을 만들고, 이를 '자식' 템플릿들이 상속받아서 이용할 수 있다.
이 방법은 웹페이지의 일관된 레이아웃을 유지하면서 코드의 반복을 피하고자 할 때 유용하다.
[템플릿 상속의 핵심 구성 요소]
- {% block 블록명 %}: 이 구문은 자식 템플릿에서 재정의 가능한 블록 영역을 설정한다. 블록명은 해당 블록의 고유한 식별자이다
- {% endblock %}: 이 태그는 블록의 종료를 나타낸다. 각각의 block 선언은 반드시 이 태그로 종결되어야 한다
- {% extends 파일명 %}: 자식 템플릿에서 이 구문을 사용하여 특정 부모 템플릿을 상속받을 것임을 명시한다
[템플릿 구성요소 예시]
먼저 기본 레이아웃을 정의한다. (base.html)
base.html은 다른 HTML 파일이 상속받을 수 있는 템플릿으로, 웹사이트의 기본적인 구조를 정의한다.
<!-- templates/baes.html-->
<!DOCTYPE html>
<html lang='kr'>
<head>
<!-- 'block'은 자식 템플릿이 재정의할 수 있는 플레이스홀더-->
<!-- 'pagetitle'은 블록의 이름으로, 이 이름을 가진 블록을 자식 템플릿이 재정의-->
<title>{% block pagetitle %} 기본 웹사이트 {% endblock pagetitle %}</title>
</head>
<body>
<header>
<h1>나의 웹사이트 방문을 환영합니다!</h1>
</header>
<!-- 여기서 정의한 'maincontent' 블록은 자식 템플릿에서 내용을 채워 넣기 위한 표시자-->
{% block maincontent %}
<!-- 이 부분은 자식 템플릿에서 구체적으로 채워질 내용-->
<!-- 'maincontent' 블록 안에 내용을 추가하여 기본 레이아웃을 확장-->
{% endblock maincontent %}
<footer>
<p>© 나의 웹사이트</p>
</footer>
</body>
</html>
그리고 개별 내용을 추가하기 위한 자식 템플릿을 만든다. (about.html)
자식 템플릿은 base.html의 레이아웃을 상속받아서 특정 내용을 추가한다.
<!-- templates/about.html-->
<!-- 'extends' 태그를 사용하여 'base.html'을 상속받겠다고 선언-->
<!-- 이는 'about.html'이 'base.html'의 블록을 재정의할 수 있음을 의미-->
{% extends 'base.html' %}
<!-- 'pagetitle' 블록을 재정의하여 이 페이지의 타이틀을 정의-->
<!-- 타이틀은 'About - 나의 웹사이트' 로 설정-->
{% block pagetitle %} About - 나의 웹사이트 {% endblock pagetitle %}
<!-- 'maincontent' 블록을 재정의하여 '우리에 대해서' 섹션 추가-->
{% block maincontent %}
<h2> 우리에 대해서 </h2>
<p>이 페이지는 나의 웹사이트에 관한 정보를 제공합니다</p>
{% endblock maincontent %}
마지막으로 플라스크에서 템플릿을 랜더링한다.
플라스크 애플리케이션에서는 render_template() 함수를 사용하여 특정 경로에 해당하는 HTML 템플릿을 랜더링한다.
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/about')
def about_page():
# 'render_template' 함수를 사용하여 'about.html' 템플릿을 랜더링
# 플라스크는 'about.html'과 함께 이 템플릿이 상속하는 모든 부모 템플릿('base.html')을
# 랜더링하여 최종 HTML을 생성
return render_template('about.html')
http://127.0.0.1:5000/about 에 접속하면 about.html 페이지가 표시된다.
▶ about.html은 base.html에 정의된 레이아웃을 기반으로 하되, pagetitle과 maincontent 블록에 about.html에서 정의한 내용이 채워져 있어 페이지별로 고유한 정보를 제공하면서도 일관된 구조를 유지할 수 있다.
참고로, pagetitle 부분은 웹페이지 타이틀로 보통 아래와 같이 웹 브라우저 탭에 표시된다.
'[파이썬 Projects] > <파이썬 웹개발>' 카테고리의 다른 글
[파이썬] 플라스크(Flask) - 블루프린트 (0) | 2024.07.15 |
---|---|
[파이썬] 플라스크(Flask) - 정적 파일 (0) | 2024.07.14 |
[파이썬] 플라스크(Flask) - 요청과 응답 (1) | 2024.07.14 |
[파이썬] 플라스크(Flask) - 라우팅 (2) (1) | 2024.07.14 |
[파이썬] 플라스크(Flask) - 라우팅 (1) (0) | 2024.07.13 |