Flask 소개
장고 (Django) 나 플라스크 (Flask) 에 대해서는 파이썬을 접하게 되면 한 번은 들어보셨을 수도 있을 겁니다.
이 두 개는 파이썬을 사용해 웹 애플리케이션을 작성할 수 있도록 도와줍니다.
Flask 란?
Flask 는 마이크로 웹 프레임워크입니다 (Micro Web Framework).
웹 프레임워크는 웹 애플리케이션을 개발할 수 있도록 웹 서비스 (Web Service) 나 웹 API (Web API) 등을 제공하고 웹 개발과 배포를 할 수 있는 특정 방법을 제공합니다. 쉽게 말해 뭔가를 만들어낼 수 있는 도구 모음을 제공한다고 보시면 됩니다.
Flask 는 웹 프레임워크이긴 한데 '마이크로' 가 앞에 붙습니다. 즉, 이러한 도구 모음들이 최소한의 크기로 줄여진 거죠. 예를 들어 일반적인 웹 프레임워크를 손톱깎이 세트로 비유하자면 손톱깎이를 비롯한 여러 가지가 들어가 있는 겁니다. Flask 는 여기에서 정말 최소한의 도구들을 모아놓은 거죠.
기본적으로 프레임워크에 따라 패키지와 라이브러리 등 모듈들의 컬렉션이 있어 개발이 수월할 수 있도록 도와줍니다. 앞으로 배우겠지만 Jinja, Werkzeug, Flask-SQLAlchemy 등 다양한 패키지들과 라이브러리들이 존재합니다.
Flask 작동 방식
Flask 프레임워크는 템플릿 처리 애플리케이션인 Jinja2와 WSGI(서버 측에서 실행되는 Python 프로그램과 웹 서버 자체 간의 상호 작용을 위한 표준) 작업 도구인 Werkzeug를 사용합니다.
Python에서 격리된 환경을 만들려면 Virtualenv 모듈이 사용됩니다.
장점
- 소규모 정적 사이트와 경량 웹 애플리케이션을 만들기 위한 최고의 웹 프레임워크로 간주됩니다.
- 대부분의 작업 도구를 편집할 수 있습니다.
- 직관적인 구문과 간단한 구조를 가지고 있습니다.
- 디버깅 및 테스트를 위한 도구(단위 테스트, 내장 개발 서버, 요청 처리기 및 디버거)가 있습니다.
- 2.0부터. 프로그램 흐름을 차단하지 않고 프로세스를 실행하는 데 도움이 되는 기술인 비동기성을 지원합니다. 이를 통해 생산성과 속도가 향상됩니다.
단점
- 데이터베이스에 연결하고, 양식 데이터의 유효성을 검사하고, 파일을 업로드하려면 확장 기능을 사용해야 합니다.
Flask 시작하기
설치
Flask 를 시작하기 위해서는 먼저 설치를 해야 합니다.
$ pip install flask
폴더 생성하기
먼저 Flask 애플리케이션을 저장할 폴더를 새로 생성해 줍니다.
이름은 주로 애플리케이션 이름으로 지정해 줍니다.
그리고 그 안에 __init__.py 이라는 파일을 하나 만들어보겠습니다.
다음과 같은 구조가 되었습니다.
flask_app
└── __init__.py
Flask 애플리케이션 생성하기
이제는 __init__.py 파일에 코드를 담아보겠습니다.
먼저 Flask 를 사용해서 웹 애플리케이션을 만드는 방법은 다음과 같습니다.
# __init__.py
from flask import Flask
app = Flask(__name__)
보시면 Flask(__name__) 은 해당 애플리케이션의 이름을 지정해 주고 있습니다.
여기까지 하면 Flask 웹 애플리케이션을 생성한 겁니다.
CLI 로 실행하기
CLI 명령어로 실행할 때에는 프로젝트 폴더 상위 디렉토리에서 다음과 같이 실행해 주면 됩니다.
$ FLASK_APP=flask_app flask run
여기서 가장 밑에 적혀 있는
* Running on http://127.0.0.1:5000
flask 웹 애플리케이션을 시작했는데 이 애플리케이션에 접속할 수 있는 주소를 알려주고 있습니다.
127.0.0.1 은 localhost 이고 5000번 포트에서 작동하고 있다는 뜻입니다.
웹 브라우저를 키고 접속해 보면 애플리케이션에 접근할 수 있지만 아무 설정도 없기 때문에 404 (Not Found) 페이지가 보이게 될 겁니다.
라우트 추가하기
이제는 애플리케이션에 접속하면 'Hello World!' 를 띄어보겠습니다.
먼저 기존에 작성했던 파일에서 작업을 이어나가겠습니다.
# __init__.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello World!'
하나씩 살펴보겠습니다.
먼저 @app.route('/') 는 애플리케이션의 루트 주소 ('/') 에 접속했을 때에 실행하라는 뜻입니다.
URL 에 따라 실행하게 될 함수를 지정하는 역할입니다.
즉, 엔드 포인트 (endpoint) 를 설정하게 되는데 이때 엔드 포인트란 주소가 어떻게 끝나는지를 말하고 있는 겁니다.
여기에서는 '/' 로 끝나기 때문에 기본 URL (Base URL) 인 127.0.0.1:5000 + / 로 결국에는 127.0.0.1:5000/ 로 됩니다. 만약에 다른 엔드 포인트인 /about 를 설정하게 된다면 127.0.0.1:5000/about 에 접속할 수 있게 되는 겁니다. 기본적으로 기본 URL 뒤에는 슬래시 ( / ) 가 붙어야 하기 때문에 없이 그저 @app.route('about') 와 같은 설정은 Flask 를 실행할 때에 에러를 일으킵니다.
실제로 실행하게 되는 함수는 아래에 있는 index 함수를 실행하게 됩니다. 그리고 index 함수가 실행되면서 리턴되는 값 Hello World! 가 웹 페이지에 보이게 됩니다.
이제 다시 CLI 에서 FLASK_APP=flask_app flask run 으로 실행해서 마찬가지로 127.0.0.1:5000/ 주소에 접속하게 되면 'Hello World!' 라는 문구가 눈의 띌 겁니다.
라우트 기능들
Flask 에서는 라우트를 다양하게 설정할 수가 있습니다. 앞서 했던 것처럼 기본적으로 엔드 포인트를 지정할 때도 있지만 URL 내에서 변수를 받을 상황도 있을 수 있습니다. 그리고 시각적인 부분 없이 접속이 되는 라우트들도 있을 수 있겠죠.
이러한 기능들을 여기에서 다 다루지는 않겠지만 몇 가지만 살펴보겠습니다.
HTTP Request 메서드
기본적으로 Flask 의 라우트 데코레이터를 사용하게 되면 3가지 HTTP Request 메서드를 허용합니다. 바로 GET, HEAD, OPTIONS 이죠. 하지만 이외에 POST, PUT, PATCH, DELETE 등 다른 메서드들을 통과하도록 설정하기 위해서는 데코레이터 함수에 methods 라는 인자를 추가해주면 됩니다.
예를 들어 @app.route('/') 에 POST 메서드를 추가하려면 다음과 같이 할 수 있습니다.
@app.route('/', methods=['POST', 'GET'])
def index():
...
보시면 이제는 GET 과 POST 라는 메서드가 통과됩니다. HEAD 와 OPTIONS 라는 메서드들은 이제 사용이 불가능합니다.
세부 엔드 포인트
URL 을 보다 보면 슬래시 ( / ) 로 이어진 긴 엔드 포인트들이 있습니다. 예를 들어 유어클래스에서 코스 카드를 하나 선택하면 다음과 같은 URL 이 하나 뜨게 됩니다.
https://www.test.com/item/100/list
여기에서 itme 뒤에 100 이라는 숫자가 보이고 list 이라는 단어가 잇따라 옵니다.
이처럼 URL 을 세부적으로 지정하고 주소에서 값을 전달할 수도 있습니다.
작업하는 Flask 애플리케이션에 index 라우트를 만들고 index 의 번호에 따라 해당 번호가 포함된 Welcome to Index { 번호 } 를 리턴한다고 해보겠습니다.
즉, http://127.0.0.1:5000/index/1 에 접하면 Welcome to Index 1 이 보이고 http://127.0.0.1:5000/index/5 에 접하게 되면 Welcome to Index 5 가 보이게 할 겁니다.
다음과 같이 라우트 설정할 때 엔드포인트에 꺽쇠 (< >) 모양으로 어떠한 변수를 받겠다고 설정할 수 있습니다. 그리고 꺽쇠 안에는 변수의 이름을 지정해주고 함수에서는 변수를 그대로 받아 사용할 수 있습니다.
@app.route('/index/<num>')
def index_number(num):
return 'Welcome to Index %i' % int(num)
한번 살펴보겠습니다 :
- 먼저 <num> 으로 num 이라는 이름의 변수를 만들어 받게 되어있습니다. 따라서 사용자가 입력하는 값과 상관없이 변수로 받게 됩니다. 만약에 index/hello 를 넘겨주면 hello 가 값이 되겠죠? 따라서 변수의 타입을 신경 써야 하기도 합니다.
- 다음은 int(num) 으로 들어오는 변숫값을 타입 변환해 주고 있습니다. 그 이유는 기본적으로 URL 을 통해 들어오게 되는 값은 문자열 타입이기 때문입니다. 따라서 숫자로 표현하기 위해서는 변환해 주는 작업이 필요합니다.
- 처음부터 받을 때에 타입을 지정할 때에는 이렇게 표기할 수도 있습니다 @app.route('/index/int:num')
이렇게만 설정해도 index/2 에 접속하게 되면 Welcome to Index 2 가 정상적으로 보이게 됩니다.
만약에 숫자를 넘겨주지 않으면 어떻게 될까요? 예를 들어 숫자가 안 주어지면 0 을 기본으로 설정해 주는 방법은 다음과 같습니다.
@app.route('/index/', defaults={ 'num' : 0 })
@app.route('/index/<num>')
def index_number(num):
return 'Welcome to Index %i' % int(num)
블루프린트 사용하기
기능이 많아질수록 라우트도 많아지기 마련입니다.
그렇기 때문에 이러한 라우트들을 하나의 파일로 모아서 사용하지 않고 기능별로 나눠서 블루프린트 기능을 사용합니다. 블루프린트는 Flask 에서 여러 개의 라우트를 한곳에 묶어둘 수 있는 기능이 있습니다.
사용하는 방법은 다음과 같습니다 :
그리고 routes 라는 폴더를 만들어 그 안에 user_routes.py 라는 파이썬 파일을 생성합니다.
이제 프로젝트 구조는 다음과 같이 생겼습니다 :
flask_app
├── __init__.py
└── routes
└── user_routes.py
그리고 user_routes.py 파일에는 다음과 같이 코드를 작성합니다.
# user_routes.py
from flask import Blueprint
bp = Blueprint('user', __name__, url_prefix='/user')
@bp.route('/')
def index():
return 'User index page'
위에서 Blueprint 의 인수로 들어가는 것은 다음과 같습니다:
- 'user' : 블루프린트의 명칭
- name : 블루프린트의 import 이름
- url_prefix='/user' : URL 접두어 설정 (해당 블루프린트의 라우트는 URL 앞에 '/user' 가 자동으로 붙게 됩니다.)
그리고 __init__.py 파일에서 해당 파일을 불러와서 사용할 수 있습니다.
# __init__.py
from flask import Flask
from flask_app.routes import user_routes
app = Flask(__name__)
app.register_blueprint(user_routes.bp)
@app.route('/')
def index():
return 'Hello World!'
(... 생략 ...)
이제 실행을 한 뒤에 http://127.0.0.1:5000/user 로 접하게 되면 User index page 라는 문구가 보이게 됩니다.
Application Factory
프로젝트가 커지고 파일들이 많아지면 import 를 사용할 일이 많아집니다.
이때 파이썬에서 circular import 를 피하기 위해서 Flask 에서는 애플리케이션 팩토리 패턴을 추천하고 있습니다.
말 그대로 애플리케이션을 만드는 '공장' 을 세우는 겁니다.
여태까지는 글로벌한 컨텍스트에서 app 을 선언하고 사용했었습니다.
하지만 이렇게 되면 여러 개의 애플리케이션을 동시에 사용하거나 app 이 선언되어 있는 파일의 일부분만 필요할 때에도 문제가 발생할 수가 있습니다.
이러한 잠재적인 문제점들을 피하기 위해 사용되는 방법이 함수를 따로 만드는 것입니다.
기본적인 패턴은 다음과 같습니다.
__init__.py 파일에서 다음과 같은 코드가 들어가게 됩니다.
from flask import Flask
def create_app():
app = Flask(__name__)
from yourapplication.views.admin import admin
from yourapplication.views.frontend import frontend
app.register_blueprint(admin)
app.register_blueprint(frontend)
return app
if __name__ == "__main__":
app = create_app()
app.run()
보시는 것처럼 함수 안에다가 애플리케이션을 생성해 준다면 해당 함수를 실행하기만 하면 원하는 애플리케이션이 하나 만들어집니다. 이제는 다른 파일에서 import 를 해도 문제가 될 일도 줄어듭니다.
Jinja 템플릿 활용
Flask 의 HTML 렌더링
웹 브라우저에서 웹 페이지를 볼 때에는 HTML 이라는 마크업 언어를 사용하게 됩니다.
Flask 에서도 HTML 파일들을 제공하면서 웹 페이지를 클라이언트에게 보여줄 수 있습니다.
하지만 단순히 정해진 변경하지 않는 데이터와 페이지가 아닌 상황에 따라 다른 정보를 웹 페이지로 보여줘야 합니다.
하나의 방법은 파이썬 코드에서 직접적으로 HTML 을 리턴하도록 해주는 방식입니다.
예를 들어 다음과 같은 작업입니다.
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '''
<html>
<head>
<title>
HTML Page
</title>
</head>
<body>
<h1>Writing HTML...</h1>
</body>
</html>
'''
얼핏 봐도 이렇게 HTML 페이지를 서버에서 코드로 작성한다면 많은 문제가 발생할 것 같습니다.
다행히도 Flask 에서는 render_template 이라는 메서드로 html 파일들을 불러올 수 있는 방법이 있습니다.
해당 함수는 기본적으로 프로젝트 폴더 내에 'templates' 라는 이름의 폴더를 기본 경로로 설정합니다.
따라서 먼저 templates 폴더를 만들고 내부에 html 파일들을 모아두면 손쉽게 사용할 수가 있습니다.
예를 들어 templates 폴더에 다음과 같은 index.html 파일이 있다고 하겠습니다.
<html>
<head>
<title>
New HTML Page
</title>
</head
<body>
<h1>I am in templates folder</h1>
</body>
</html>
그러면 애플리케이션의 라우트에서 다음과 같이 코드를 작성하면 index.html 을 보여줄 수 있습니다.
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
만약에 templates 폴더 내에 또 다른 폴더에 있다 해도 경로는 templates 폴더 기준으로 잡아줘야 합니다.
가령 main 이라는 폴더에 'main.html' 파일이 존재한다면 파이썬에서도 다음과 같이 코드를 작성해 줘야 합니다.
(... 생략 ...)
@app.route('/main')
def main():
return render_template('main/main.html')
Jinja 소개
Flask 에서는 HTML 을 편리하게 렌더링 하는 함수를 제공을 하기 때문에 쉽게 웹 페이지를 클라이언트에 넘겨줄 수 있습니다.
물론 이 방법을 사용해서 원하는 페이지를 넘겨주면 좋겠지만 상황에 따라 다르게 보여줘야 하는 경우에는 약간 힘들 수도 있습니다. 예를 들어 오늘의 날짜를 페이지에 표시하려고 하는데 기본 HTML 으로는 수작업으로 바꿔줘야 할 수도 있습니다.
이때 유용한 도구는 Jinja 와 같은 웹 템플릿 엔진 (Web Template Engine) 입니다.
템플릿 엔진은 맞춤형 웹 페이지를 자동으로 생산할 수 있도록 도와줍니다.
장고 (Django) 의 템플릿 엔진을 모델링 했으며 파이썬 문법과 친화적인 도구라 어렵지 않게 익히고 사용할 수 있도록 되어 있습니다.
또한 Jinja 2 는 Flask 설치와 함께 오기 때문에 추가 설치가 따로 필요 없습니다.
Jinja 표현
HTML 파일에서 Jinja 를 사용할 때에는 중괄호 '{ }' 를 많이 사용합니다.
예를 들어 변수를 사용할 때에는 다음과 같이 사용할 수 있습니다.
<body><h1>{{ title }}</h1></body>
여기에서는 title 이라는 변수를 <h1> 태그 안에 넣어서 렌더링을 하는 방식입니다.
다음 3 가지가 Jinja 에서 주로 활용되는 표현식입니다 :
- {% ... %} : 구문에 사용이 됩니다 (if, for 등).
- {{ ... }} : 템플릿 결과 (html) 에 출력할 표현입니다 (변수 등).
- {# ... #} : 주석 처리할 때 사용됩니다.
Flask 에서 Jinja 로 변수 넘기기
Jinja 에 변수를 전달할 때에는 이전과 같은 render_template 함수를 사용할 수 있습니다.
해당 함수를 실행할 때에 인수로 변수를 넘겨주면 html 파일에서 받아 사용할 수가 있습니다.
예를 들어 다음과 같이 apple 과 banana 를 넘겨줄 수가 있습니다.
(... 생략 ...)
@app.route('/')
def index():
apple = 'red'
apple_count = 10
return render_template('index.html', fruit_color=apple, number=apple_count)
그리고 html 파일에서는 다음과 같이 사용이 가능합니다.
(... 생략 ...)
<body><h2>Apple is {{ fruit_color }}</h2><h2>{{ number }} 개의 과일이 있습니다.</h2></body>
(... 생략 ...)
Jinja 기능들
이제부터 주로 사용되는 객체 태그, if, 그리고 for 에 대해서 살펴보겠습니다.
Jinja 에는 훨씬 많은 기능들이 있으니 더 자세한 설명은 Jinja 공식 문서에서 확인해 주세요!
객체 태그
Flask 애플리케이션에서부터 파이썬 변수를 넘겨받아 사용할 수 있습니다.
위에서도 잠깐 봤듯이 간단한 문자열이나 숫자뿐만이 아닌 중첩된 딕셔너리나 리스트 등도 사용할 수가 있습니다.
표현하는 방식은 중괄호 두 개를 겹쳐서 변수명을 중간에 넣어주시면 됩니다.
만약에 var=[1, 2, 3] 이라면 다음과 같이 변수를 웹 페이지에 출력할 수 있습니다.
{{ var }}
파이썬의 딕셔너리나 리스트 같은 경우에는 점 표기 (dot notation) 이나 괄호 표기 (bracket notation) 로 세부적인 선택이 가능합니다.
예를 들어 fruits = { 'apple' : 'red', 'banana' : 'yellow' } 가 주어진다면 다음과 같이 'apple' 키의 값인 'red' 만 출력할 수도 있습니다.
{{ fruits.apple }}
이와 마찬가지로 리스트도 vegetables = [ 'cucumber', 'spinach' ] 가 주어진다면 다음과 같이 0 번째 인덱스의 값 ('cucumber') 을 출력할 수 있습니다.
{{ vegetables[0] }}
if 구문
Jinja 에서도 구문들을 활용할 수 있습니다. 예시를 먼저 보겠습니다.
{% if True %}
<h1>It is True</h1>
{% endif %}
더 나아가 파이썬과 비슷하게 if... elif... else 처럼 사용할 수 있습니다.
{% if %} ... {% elif %} ... {% else %} ... {% endif %}
만약에 'else' 나 'elif' 와 같은 조건을 추가해야 한다면 다음과 같이 설정할 수도 있습니다.
{% if True %}
<h1>It is True</h1>
{% elif False %}
<h1>It is False</h1>
{% else %}
<h1>It is not True</h1>
{% endif %}
for 구문
for 구문은 리스트를 받거나 딕셔너리를 받았을 때 매우 유용하게 사용할 수 있습니다. 특히 HTML 엘리먼트를 반복적으로 생성해야 하는 상황에서 도움이 되죠.
예를 들어 item_list 라는 리스트가 ['book', 'keyboard', 'window'] 일 때 for 로 순환할 수 있습니다.
{% for item in item_list %}
<p>{{ item }}</p>
{% endfor %}
이때 각 반복마다 Jinja 에서 제공하는 loop 이라는 것을 활용해 추가 정보를 얻을 수 있습니다.
loop 속성 설명
loop.index | 반복 순서 1부터 1씩 증가 |
loop.index0 | 반복 순서 0부터 1씩 증가 |
loop.first | 반복 순서가 처음일 경우 True 아니면 False |
loop.last | 반복 순서가 마지막일 경우 True 아니면 False |
인덱스를 파악할 때에 유용한 loop.index0 를 살펴보겠습니다.
{% for item in item_list %}
<p>인덱스 : {{ loop.index0 }}, 이름 : {{ item }}</p>
{% endfor %}
이외에도 loop 에는 다양한 속성들이 존재합니다. 여기에서는 몇 가지만 소개해 드리니 Jinja 문서에서 더 찾아보시길 바랍니다.
Jinja 상속
Jinja 의 다양한 기능들 중에서 가장 핵심 중 하나는 상속입니다. 반복적으로 사용되는 부분들을 하나로 묶어서 사용할 수 있게끔 해주는 기능입니다. 예를 들어 웹 애플리케이션에 네비게이션 바가 있다면 모든 HTML 파일에 넣을 필요가 없다는 뜻입니다.
이를 사용하기 위해서는 두 가지를 사용합니다:
- {% extends %}
- {% block %} ... {% endblock %}
자식 상속
Jinja 에서는 다른 템플릿 파일을 상속받아 사용할 수 있습니다. 즉 부모 - 자식 관계가 형성 가능합니다.
사용 방법은 간단합니다. 부모 템플릿의 경로를 자식 템플릿 파일의 첫 줄에 적어주게 되면 Jinja 의 템플릿 엔진이 해당 파일을 이용합니다.
예를 들어 다음과 같은 base.html 파일이 있습니다.
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<title>{% block title %}{% endblock %} - My Webpage</title>
{% endblock %}
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
© Copyright 2008 by <a href="<http://domain.invalid/>">you</a>.
{% endblock %}
</div>
</body>
</html>
그리고 새로운 child.html 파일을 base.html 파일과 같은 경로에 생성한 뒤에 base.html 파일 내용을 상속받고 싶다면 다음과 같이 작성해 주시면 됩니다.
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
{% endblock %}
{% block content %}
<h1>Index</h1><p class="important">
Welcome to my awesome homepage.
</p>
{% endblock %}
이렇게 되면 자식 파일인 child.html 은 base.html 로부터 상속을 받게 됩니다.
참고로 상속은 첫 줄에 위치해야 합니다.
또한 상속은 여러 번을 할 수 있습니다. 예를 들어 grandchild.html 도 child.html 과 base.html 과 같은 경로에 생성해 준 뒤에 child.html 을 상속받게 하려면 다음과 같이 작성해도 작동합니다.
{% extends 'child.html' %}
만약에 경로가 다르면 반영해서 파일의 위치를 잘 적어두면 됩니다.
Flask 를 사용할 때에는 templates 폴더를 기준으로 삼습니다.
진자 블록
상속에서 extends 와 관련된 설명에서 {% block %} 이라는 것을 보셨을 겁니다. 이 문구는 상속된 파일에서 변경할 수 있는 일종의 HTML '블록' 들을 지정해 줍니다.
Jinja 는 상속에서 부모와 자식 구분이 없습니다. 그렇기 때문에 한번 상속을 하면 부모 파일의 모든 것을 상속하게 됩니다. 따라서 자식 HTML 파일에서 뭔가를 작성하게 된다면 부모의 파일 내용 이후에 작성이 됩니다.
이러한 부분을 극복하기 위해서 Jinja 는 block 을 사용합니다. 각 block 은 for 나 if 처럼 시작과 끝이 있어야 합니다.
상속에서 봤던 base.html 의 <head> 부분을 살펴보겠습니다.
<head>
{% block head %}
<title>{% block title %}{% endblock %} - My Webpage</title>
{% endblock %}
</head>
보시면 'block' 이라는 단어 뒤에 'head' 나 'title' 등 단어가 붙어 있습니다. 이것은 각 block 의 이름입니다.
템플릿 엔진이 상속했을 때에 구별할 수 있도록 이름을 지어주는 겁니다. 이 이름은 중복해서 사용하면 Jinja 에서 어떤 블록을 사용해야 하는지 모르게 됩니다. 또한 자식 파일에서 부모 파일에서 사용한 블록을 사용하게 되면 새로 덮어쓰게 되어 부모 블록의 내용은 출력되지 않습니다.
자식이 부모 블록의 내용을 사용하려면 파이썬과 비슷하게 super 를 통해서 사용 가능합니다.
2번 상속된 파일이 가장 상위 부모의 내용을 접근하기 위해서는 super.super() 로도 접근 가능합니다.
상속 설명에서 나오는 'child.html' 처럼 부모의 'head' 블록 내용을 가져오고 싶을 때에는 다음과 같이 사용할 수 있습니다.
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<h1>자식 블록에서 출력한 h1 입니다.</h1>
{% endblock %}
(... 생략 ...)
'Data Engineer' 카테고리의 다른 글
Oracle VM VirtualBox를 활용해서 Linux OS 설치방법 (0) | 2023.11.02 |
---|---|
mongo db란? (0) | 2023.09.22 |
Kubernetes란? (0) | 2023.09.16 |
데이터 웨어하우스(Data Warehouse)와 데이터 레이크(Data Lake)의 차이점 (0) | 2023.09.15 |
정형 데이터 vs 반정형 데이터 vs 비정형 데이터 (0) | 2023.09.15 |