👣 개요
웹 개발의 전체적인 흐름을 파악하기 위한 Flask 지식 공부.
👣 대략적인 프로젝트 구조
📦Root
┣ 📂static
┃ ┃ 📜image.png
┃ ┃ 📜script.js
┃ ┗ 📜style.css
┣ 📂templates
┃ ┗ 📜index.html
┗ 📜app.py
static
CSS, JS, 이미지 등등의 정적 파일을 보관하는 곳.
templates
Jinja2 템플릿 파일을 보관하는 곳.
app.py
Flask 애플리케이션을 정의하고 구성하는 데 사용되는 파일.
👣 라이브러리 구성
pip install flask dnspython
참고로 dnspython은 DNS 프로토콜을 Python에서 다루기 위한 라이브러리.
👣 대략적인 app.py 구성
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def get():
return render_template('index.html')
@app.route("/call", methods=["POST"])
def post():
return 'This is the about page.'
if __name__ == '__main__':
app.run('0.0.0.0', port=5000, debug=True)
app = Flask(__name__)
해당 코드는 Flask를 이용하기 위한 Flask 객체를 만드는 과정이다.
__name__은 현재 모듈의 이름을 뜻하며,
이것을 Flask 객체에 넘겨줌으로서 해당 어플리케이션의 루트 경로를 정의한다.
@app.route('/')
해당 명령어는 라우팅(route)을 처리하기 위한 데코레이터다.
쉽게 말해 http://localhost/home으로 요청했는지 http://localhost/memo으로 요청했는지를
판단하고 그에 맞춰 처리를 하기 위한 장치라고 볼 수 있다.
위 명령어는 http://localhost/ 로 요청 시, 해당 데코레이터가 지정한 메소드로 처리하겠다라는 의미다.
해당 데코레이터로 지정한 메소드의 Return값이 주로 응답의 Body의 내용을 구성하게 되는데
이에 대한 깊은 이해는 다음 항목에서 다룰 예정이다.
if __name__ == '__main__':
app.run('0.0.0.0', port=5000, debug=True)
해당 명령줄은 실질적으로 서버의 구동을 선언하는 명령어들이다.
app.run을 호출하게 되면 그제서야 설정해준 내용들을 토대로 구동이 된다.
debug = True로 설정하면, 디버그 모드가 활성되고 코드가 수정될 때마다 Reload를 해준다.
여기서 0.0.0.0의 의미는 모든 포트에 대해 Serve하겠다는 의미다.
👣 @app.route - 메서드 편
라우팅(route)을 처리하기 위한 데코레이터다.
데코레이터의 대상인 메소드는 관련 요청을 처리하고 응답을 하는 역할을 수행해야 한다.
GET /test HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: text/html
@app.route('/test')
def index():
return 'Hello, World!'
위 코드는 첫번째에 제시한 요청에 대해 반응해 요청을 보낸다.
Flask는 다음과 같은 응답을 건네준다.
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Hello, World!
예시를 보면 알 수 있지만 index() 메소드가 Return을 문자열로 주면 Body에 해당 문자열을 전달한다.
하지만 문자열이 아닌 객체도 Return 할 수 있다.
1. 튜플
튜플은 (response, status, headers) 형식으로 반환된다.
예를 들어 다음과 같다.
@app.route('/custom_response')
def custom_response():
response = "<html><body><h1>Custom Response</h1></body></html>"
status_code = 200
headers = {'Content-Type': 'text/html'}
return response, status_code, headers
2. Response 객체
flask.Response라는 클래스의 인스턴스를 Return하면 더 세밀하게 응답할 수 있다.
from flask import Flask, Response
@app.route('/custom_response')
def custom_response():
response_text = "<html><body><h1>Custom Response</h1></body></html>"
headers = {'Content-Type': 'text/html'}
response = Response(response=response_text, status=200, headers=headers)
return response
3. 사용자 정의 클래스
만약 직접 만든 클래스라도 오류 없이 Return 할 수 있다.
해당 인스턴스의 응답은 __str__라는 매직 메서드를 사용해서 해당 문자열을 Body로 기록한다.
class CustomResponse:
def __init__(self, data):
self.data = data
def __str__(self):
return f"This is a custom response with data: {self.data}"
@app.route('/custom_response')
def custom_response():
response = CustomResponse(data="example_data")
return response
4. 딕셔너리
딕셔너리는 간단하게 Json으로 변환되어 전달된다.
@app.route('/data')
def data():
data_dict = {'name': 'John', 'age': 30, 'email': 'john@example.com'}
return data_dict
5. render_template 인스턴스
render_template는 templates 폴더 내부의 Html 파일을 찾아 해당 내용을 응답 Body에 기록하는 메서드다.
render_template는 동적으로 Html을 작성해서 출력하기도 하는데 방법은 다음과 같다.
아래 {{ }} 안에 정의된 변수에 맞춰 파라미터를 전달하면 해당 자리에 값이 기입되어 응답한다.
참고로 해당 메서드가 사용하는 템플릿 엔진의 이름은 Jinja2다.
@app.route('/hello')
def hello():
name = "Name Example"
return render_template('hello.html', name=name)
<!-- root/templates/hello.html -->
<!DOCTYPE html>
<html>
<head>
<title>Hello Page</title>
</head>
<body>
<h1>Hello, {{ name }}!</h1>
</body>
</html>
👣 @app.route - URL 파라미터 추출
URL를 동적으로 감지하고 해당 URL를 파싱해서 처리해야 할 때가 존재한다.
예를 들어, http://localhost/user-page/102345 라는 URL로 요청이 들어올 때,
회원 번호 102345 인 사람의 유저 페이지를 건네줘야 하는 상황이 찾아 온다.
이런 경우를 대비해 다음과 같은 규칙이 존재한다.
@app.route('/user/<int:user_id>')
def get_user(user_id):
return f"User ID: {user_id}"
위와 같이 < > 내부에 "{타입 Converter}:{변수명}" 혹은 "{변수명}"을 적으면 알아서 파싱을 해준다.
참고로 타입 Converter는 메서드 이름을 괄호 없이 전달하면 된다.
만약 Converter를 지정하지 않으면 문자열로 Parsing 해준다.
👣 @app.route - Parameter 사용
URL에 함께 딸려오는 parameter들을 사용하려면 다음과 같이 request를 사용해야 한다.
GET /user?name=iksadnorth&gender=m HTTP/1.1
Host: localhost:5000
from flask import request
@app.route('/hello')
def hello():
key = request.args.get('key_name', "default value")
return "Hello, World!"
👣 @app.route - form data 사용
요청을 Form 형식으로 준다면 다음과 같이 데이터를 받을 수 있다.
POST /form HTTP/1.1
Host: localhost:5000
Content-Type: application/x-www-form-urlencoded
name=John&email=john@example.com
@app.route('/form', methods=['POST'])
def process_form():
name = request.form['name']
email = request.form['email']
return f"Name: {name}, Email: {email}"
👣 @app.route - Json data 사용
요청을 Json 형식으로 준다면 다음과 같이 데이터를 받을 수 있다.
POST /json HTTP/1.1
Host: localhost:5000
Content-Type: application/json
{
"name": "John",
"email": "john@example.com"
}
@app.route('/json', methods=['POST'])
def process_json():
data = request.get_json()
name = data['name']
email = data['email']
return f"Name: {name}, Email: {email}"
'항해 99' 카테고리의 다른 글
Web Scraping (0) | 2023.08.05 |
---|---|
Jinja2 템플릿 엔진 (0) | 2023.08.05 |
mongo Atlas (0) | 2023.08.04 |
Github Pages 배포 (0) | 2023.08.03 |
CSS 선택자 (0) | 2023.08.03 |