Python

[Python] Flask 기초 사용법

열지희공 2022. 1. 26. 01:33

기본 어플리케이션

from flask import Flask
app = Flask(__name__)

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

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

위와 같은 코드를 입력하면 Hello World!를 출력하는 단순한 웹 어플리케이션을 만들 수 있다. 

app = Flask(__name__)을 통해 Flask class의 인스턴스를 생성한다. 인자로는 모듈이나 패키지의 이름을 넣는다. 

route()데코레이터를 사용해서 Flask에게 어떤 URL이 우리가 작성한 함수를 실행시키는지 알려줄 수 있다.

마지막 줄의 app.run()을 통해 개발한 어플리케이션을 로컬서버로 실행한다. 

if __name__ == '__main__'을 통해 우리가 실행한 서버가 현재 동작되는 유일한 서버라는 것을 보장할 수 있다.

실행시켜보면 터미널에 위와같은 문구를 볼 수 있고 http://127.0.0.1:5000 으로 이동해보면 아래와 같은 웹을 확인할 수 있다.

Routing

from flask import Flask

app = Flask(__name__)

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

@app.route('/<user>')
def user(user):
    return f'Hello, {user}!'

@app.route('/user/<username>')
def show_user_profile(username):
    return 'User %s' % username

@app.route('/post/<int:post_id>')
def show_post(post_id):
    return 'Post %d' % post_id

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

위에서 본 것 처럼 route()데코레이터는 함수와 URL을 연결해준다. 

위 코드에서 @app.route('/')는 Flask에게 바로 밑의 hello_world()함수를 실행시키라고 알려준다.  http://127.0.0.1:5000/ 에 들어간다면 hello_world()의 결과인 Hello World!가 출력된 것을 볼 수 있을 것이다.

URL을 동적으로 구성할 수도 있다. URL의 변수부분을 추가하기 위해서 <variable_name>이렇게 URL에 특별한 형식으로 표시해야한다. 이 부분은 함수의 키워드 인자로써 넘어가게 된다. 

@app.route('/<user>') 부분

@app.route('/user/<username>') 부분

@app.route('/post/<int:post_id>') 부분

 

Rendering Templates

from flask import Flask

app = Flask(__name__)

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

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

이런식으로 python 파일에서 직접 html 코드를 입력할 수도 있지만 render_template()메소드를 이용해 템플릿을 렌더링해줄 수도 있다.

hello.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>Hello from Flask</title>
</head>
<body>
    <h1>HTML template</h1>
</body>
</html>

user.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>User from Flask</title>
</head>
<body>
    <h1>hello {{user}}</h1>
</body>
</html>

main.py

from flask import Flask, render_template

app = Flask(__name__)

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

@app.route('/user/<username>')
def user(username):
    return render_template('user.html', user=username)


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

render_template()메소드를 사용하기 위해선 템플릿 이름과 템플릿에 보여질 키워드 인자를 넘겨주면 된다. 그러면 Flask는 templates 폴더에서 템플릿을 찾고 그 템플릿을 렌더링해준다. 대신 그 템플릿은 꼭 templates 폴더 안에 존재해야 한다. 

return render_template('hello.html') 부분

return render_template('user.html', user=username) 부분

URL을 통해 받은 키워드 인자 username을 user.html 템플릿에 user로 넘겨주고 있다.

 

URL의 query argument에 접근하기

hello.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>Hello from Flask</title>
</head>
<body>
    <form action= "/user" method= "get">
        <input placeholder="input your name" name="name"/>
        <button>click</button>
    </form>
    
</body>
</html>

/에서 위의 hello.html을 렌더링 한다면 웹의 /주소에서는 아래와 같이 보여질 것이고 input에 넣는 값이 url의 parameter로 들어오게 된다. 

input에 jihee를 입력하였다면 url에 /user?name=jihee 이런식으로 들어가게 된다. 

만약 위의 input에 넣은 parameter값을 얻고 싶다면 request.args.get('key')를 이용하면 된다.

from flask import Flask, render_template, request

app = Flask(__name__)

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

@app.route('/user')
def user():
    name = request.args.get('name')
    return render_template('user.html', name=name)

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

request.args.get('name')은 key이름이 name인 value 값을 가져오게 된다. 위의 input에 jihee를 입력하면 jihee를 가져오고, abcd를 입력하면 abcd를 가져오게 되고 이를 이용할 수 있다. 

나는 입력된 것을 포함해 다시 출력해주고 싶어서 request.args.get('name')으로 가져온 값을 다시 render_template()의 인자로 넘었고 user.html에서 이 인자를 포함해 hello {{name}}을 출력해 주었다. 

user.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>User from Flask</title>
</head>
<body>
    <h1>hello {{name}}</h1>
</body>
</html>

 

redirect

사용자가 다른 엔드포인트로 redirect하기 위해서는 redirect()함수를 사용할 수 있다.

hello.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>Hello from Flask</title>
</head>
<body>
    <form action= "/user" method= "get">
        <input placeholder="input your name" name="name"/>
        <button>click</button>
    </form>
    
</body>
</html>

main.py

from flask import Flask, render_template, request, redirect, url_for
app = Flask(__name__)

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

@app.route('/user')
def user():
    name = request.args.get('name')
    if name:
        return render_template("user.html",name=name)
    else:
        return redirect('/error')

@app.route('/error')
def erorr():
    return "ERORR!"

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

위 코드에서는 만약 사용자가 아무것도 입력하지 않아 name이 None이 된다면 /error 로 redirect하도록 한 것이다. 

만약 사용자가 아무것도 입력하지 않는다면 아래와 같은 화면을 볼 수 있다.

 

send_file()

client에게 file을 보내고 싶다면(사용자가 file을 다운받을 수 있도록하고싶다면) send_file()을 이용하면 된다. 함수인자로는 filename or fp, attachment_filename, as_attachment를 보내주면 된다. filename or fp에는 보내고 싶은 파일의 이름이나 파일경로, attachment_filename은 보내고 싶은 파일의 이름과 다르게 파일을 첨부하고 싶을 때 첨부하고 싶은 파일의 이름, as_attachment는 파일을 첨부할지 여부이다.

hello.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>Hello from Flask</title>
</head>
<body>
    <form action= "/user" method= "get">
        <input placeholder="input your name" name="name"/>
        <button>click</button>
    </form>
    
</body>
</html>

user.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>User from Flask</title>
</head>
<body>
    <h1>hello {{name}}</h1>
    <a href="/download?name={{name}}">Download</a>
</body>
</html>

main.py

from fileinput import close
from flask import Flask, render_template, request, redirect, send_file
app = Flask(__name__)

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

@app.route('/user')
def user():
    name = request.args.get('name')
    if name:
        return render_template("user.html",name=name)
    else:
        return redirect('/error')

@app.route('/download')
def download():
    name = request.args.get('name')
    file = open("name.txt", mode="w")
    file.write(f"username is {name}")
    file.close()
    return send_file("./name.txt", attachment_filename=f"{name}.txt", as_attachment=True)
     

@app.route('/error')
def erorr():
    return "ERORR!"

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

 

/user에서 download 링크를 클릭하면 실행되는 download함수는 query argument 중 key값이 name인 것을 가져와  name.txt 파일에 "username is {name}"을 쓰고 그 name.txt 파일을 {name}.txt 파일로 보내게 된다. 

 

 

 

 

<참조>

https://flask-docs-kr.readthedocs.io/ko/latest/quickstart.html

 

빠르게 시작하기 — Flask 0.11-dev documentation

웹 어플리케이션에 있어서 클라이언트에서 서버로 보내는 데이타를 처리하는 것은 중요한 일이다. Flask에서 이 정보는 글로벌한 request 객체에 의해 제공된다. 여러분이 파이썬 경험이 있다면,

flask-docs-kr.readthedocs.io