본문 바로가기

웹 프레임워크/Flask

Flask - Python 마이크로 웹 프레임워크

Flask란?

Flask는 Python으로 작성된 마이크로 웹 프레임워크로 최소한의 기능만을 제공 하지만 다양한 확장을 지원합니다. 또한 규칙이 엄격하지 않아 개발자가 원하는 구조로 설계 할 수 있습니다. 따라서 간단할 수도 있고 복잡할 수도 있습니다.

Flask 설치

pip install Flask

Flask 실행

app.py

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'

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

실행 - 터미널:

python app.py

접속 주소는 http://localhost:5000/ 입니다.

Flask 실행 옵션

app.run() 인자 값으로 다양한 옵션을 설정 할 수 있습니다.

if __name__ == '__main__':
    app.run(host='0.0.0.0', port='5050', debug=True)
  • host: Flask 서버에 접속할 수 있는 IP 주소를 설정합니다. '0.0.0.0'은 모든 IP 주소를 의미합니다.
  • port: 서비스 포트를 설정합니다. 기본값은 5000 입니다.
  • debug: 디버그 모드를 설정합니다. 기본값은 False 입니다.

접속 주소는 http://localhost:5050/ 입니다.

라우팅 (Routing)

from flask import Flask

app = Flask(__name__)   # Flask 객체 생성(__name__ 이름으로)

@app.route('/')
def home():
    return '<h1>Hello Flask!</h1>'
# http://localhost:5000/

@app.route('/member')
def member():
    return '<h1>Member</h1>'
# http://localhost:5000/member    

@app.route('/board')
def board():
    return '<h1>Board</h1>'
# http://localhost:5000/board

if __name__ == '__main__':
    app.run()
  • @app.route('/'): 라우팅 경로를 설정합니다.
  • def home():: 라우팅 경로에 접속시 실행할 함수를 정의합니다.
    • 함수의 이름이 중복되면 안됩니다.
  • return '<h1>Hello Flask!</h1>': 라우팅 경로에 접속시 반환할 값을 설정합니다.

경로 변수

from flask import Flask

app = Flask(__name__)

@app.route('/job/<jobname>')
def job(jobname):
    return '<h1>Job: ' + jobname + '</h1>'    
# http://localhost:5000/job/develper

if __name__ == '__main__':
    app.run()
  • @app.route('/job/<jobname>'), def job(jobname): URL 경로를 'jobname' 변수로 설정합니다.

접속 주소는 http://localhost:5000/job/developer 입니다.

결과는 Job: developer 입니다.

템플릿 엔진 (Jinja2)

이전 포스트에 템플릿 엔진에 대한 자세한 설명이 있습니다. 여기서는 Flask에서 템플릿 엔진의 적용법을 간단하게 보겠습니다.

'templates' 디렉토리를 생성하고 HTML(템플릿) 파일을 만듭니다.

templates/home.html

<!DOCTYPE html>
<html>
<head>
    <title>Home</title>
</head>
<body>
    <h1>Home</h1>
</body>
</html>

member.html

<!DOCTYPE html>
<html>
<head>
    <title>Member</title>
</head>
<body>
    <h1>Member</h1>
</body>
</html>

job.html

<!DOCTYPE html>
<html>
<head>
    <title>Job</title>
</head>
<body>
    <h1>Job: {{ jobname }}</h1>
</body>
</html>

controll_for.html

<!DOCTYPE html>
<html>
<head>
    <title>Controll For</title>
</head>
<body>
    <h1>Controll For</h1>
    <ul>
        {% for board in boards %}
        <li>{{ board }}</li>
        {% endfor %}
    </ul>
</body>
</html>

controll_if.html

<!DOCTYPE html>
<html>
<head>
    <title>Controll If</title>
</head>
<body>
    <h1>Controll If</h1>
    {% if score >= 90  %}
    <li>A학점</li>
    {% elif score >= 80  %}
    <li>B학점</li>
    {% elif score >= 70  %}
    <li>C학점</li>
    {% elif score >= 60  %}
    <li>D학점</li>
    {% else  %}
    <li>F학점</li>
    {% endif %}
</body>
</html>

app.py

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('home.html')
# http://localhost:5000/

@app.route('/member')
def member():
    return render_template('member.html')

### 데이터
@app.route('/job/<jobname>')
def job(jobname):
    return render_template('job.html', jobname=jobname)
# http://localhost:5000/job/developer


@app.route('/controll_for')
def controll_for():
    boards = ['title_1', 'title_2', 'title_3']
    return render_template('controll_for.html', boards=boards)
# http://localhost:5000/controll_for


@app.route('/controll_if')
def controll_if():
    score = 72
    return render_template('controll_if.html', score=score)
# http://localhost:5000/controll_if

if __name__ == '__main__':
    app.run()
  • render_template('home.html'): 'home.html' 파일을 렌더링 합니다.
  • render_template('job.html', jobname=jobname): 'job.html' 파일을 렌더링 하면서 'jobname' 변수를 전달합니다.
  • for 문과 if 문을 사용하여 반복문과 조건문을 사용할 수 있습니다.

정적 파일 (Static Files)

'static' 디렉토리를 생성하고 정적 파일을 저장합니다.

static/styles.css

body {
    background-color: silver;
}

h1 {
    font-family: "Times New Roman", Georgia, Serif;
    text-align: center;
}

p {
    color: #663399;
    text-decoration:underline;
    font-weight: bold;
}

static/scripts.js

function alertDialogBox() {
    alert("확인을 누를 때까지 다른 작업을 할 수 없어요!");
}

'templates' 디렉토리에 HTML 파일을 만듭니다.

templates/css_js.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flask Render</title>
    <link href="/static/styles.css" rel="stylesheet" />
    <script src="/static/scripts.js"></script>
</head>
<body>
    <h1>Hello Flask</h1>
    <p>아래의 버튼을 Click 하세요!</p>
    <input type="button" value="Click" onclick="alertDialogBox();">
</body>
</html>

app.py

from flask import Flask, render_template

app = Flask(__name__, static_url_path='/static')


@app.route('/css_js')
def css_js():
    return render_template('css_js.html')
# http://localhost:5000/css_js    

if __name__ == '__main__':
    app.run(host='0.0.0.0', port='5050', debug=True)
  • app = Flask(__name__, static_url_path='/static'): 정적 파일 경로를 설정합니다.

접속 주소는 http://localhost:5000/css_js 입니다.

요청 객체 (Request Object)

request 객체를 사용하여 클라이언트의 요청 정보를 확인 할 수 있습니다.

templates/.html: 생략 - 기존과 동일

templates/request_form.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <title>Flask Request</title>
</head>
<body>
    <h1>A Link - get</h1>
    <p><a href="/request_get?name=hong&age=17">request get</a></p>

    <p></p>

    <h1>Form - post</h1>
    <form name="form_post" method="post" action="/request_post">
        <p>Name: <input type="text" name="name" /></p>
        <p>Age: <input type="text" name="age" /></p>
        <p><input type="submit" ></p>
    </form>
</body>
</html>

templates/request_result.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flask Render</title>
</head>
<body>
    <h1>A Link get</h1>
    <p>Name: {{ name }}</p>
    <p>Age: {{ age }}</p>
</body>
</html>

app.py

from flask import Flask, render_template, request

app = Flask(__name__)


@app.route('/request_get_form')
def request_get_form():
    return render_template('request_form.html')

@app.route('/request_get', methods = ['GET'])
def request_get():
    name = request.args.get('name')
    age = request.args.get('age')
    return render_template('request_result.html', name=name, age=age)    

@app.route('/request_post', methods = ['POST'])
def request_post():
    name = request.form['name']
    age = request.form['age']
    return render_template('request_result.html', name=name, age=age)        

if __name__ == '__main__':
    app.run()
  • request.args.get('name'): GET 방식으로 전달된 데이터를 가져옵니다.
  • request.form['name']: POST 방식으로 전달된 데이터를 가져옵니다.

접속 주소는 http://localhost:5000/request_get_form 입니다.

Blueprint

Blueprint는 Flask의 모듈화 방법으로 여러 개의 라우트와 뷰를 하나의 모듈로 묶어서 사용할 수 있습니다.

디렉토리 구조

root/
    app.py
    templates/
        home.html
        code/
            code.html
        todo/
            todo.html
    apps/
        __init__.py
        code/
            __init__.py
            code.py
        todo/
            __init__.py
            todo.py

templates/home.html: 생략

templates/code/code.html

<!DOCTYPE html>
<html>
<head>
    <title>Code</title>
</head>
<body>
    <h1>Code</h1>
    <p>command: {{ command }}</p>
</body>
</html>

templates/todo/todo.html

<!DOCTYPE html>
<html>
<head>
    <title>Todo</title>
</head>
<body>
    <h1>Todo</h1>
    <p>command: {{ command }}</p>
</body>
</html>

apps/code/code.py

from flask import Blueprint, render_template, request
from . import code_app

@code_app.route('/', methods=['GET'])
def code():
    command = request.args.get('command')
    return render_template('code/code.html', command=command)
  • from . import code_app: Blueprint 객체를 가져옵니다.
  • @code_app.route('/'): Blueprint 객체의 라우팅 경로를 설정합니다.
  • 접속 주소는 http://localhost:5000/code?command=python 입니다.

apps/todo/todo.py

from flask import Blueprint, render_template, request
from . import todo_app

@todo_app.route('/', methods=['GET'])
def todo():
    command = request.args.get('command')
    return render_template('todo/todo.html', command=command)
  • from . import todo_app: Blueprint 객체를 가져옵니다.
  • @todo_app.route('/'): Blueprint 객체의 라우팅 경로를 설정합니다.
  • 접속 주소는 http://localhost:5000/todo?command=python 입니다.

app.py

from flask import Flask, render_template, request
from apps.code import code_app
from apps.todo import todo_app

app = Flask(__name__, static_url_path='/static')

app.register_blueprint(code_app, url_prefix='/code')
app.register_blueprint(todo_app, url_prefix='/todo')


@app.route('/')
def home():
    return render_template('home.html')

if __name__ == '__main__':
    app.run()
  • app.register_blueprint(code_app, url_prefix='/code'): '/code' 경로로 code_app Blueprint 객체를 등록합니다.
  • app.register_blueprint(todo_app, url_prefix='/todo'): '/todo' 경로로 todo_app Blueprint 객체를 등록합니다.