View에서 Controller로 user data를 가져오는 방법은 3가지이다.
www.example.com/foo?field1=value1
Requests
object에 있는 args
object를 제공한다.value1 = request.args.get('field1')
request.form.get('<name>')
은 HTML에서 name
attribute에 따라서 form에 들어간 값들을 읽어온다.username = request.form.get('username')
request.args.get
, request.form.get
은 모두 optional second parameter를 가질 수 있다.request.args.get('foo', 'my default')
는 result가 비어있을 때 기본 값으로 my default
를 가진다.request.data
는 JSON을 string으로 가져온다(retrieves). 그리고 json.loads
를 호출해서 request.data
string을 파이썬의 lists나 dictionaries로 변환한다.application/json
일때data_string = request.data
data_dictionary = json.loads(data_string)
<form action="/create-todo" method="post">
<div>
<label for="name">Create a To-Do Item</label>
<input type="text" id="description" name="description">
</div>
<div>
<input type="submit" id="submit" value="Create" />
</div>
</form>
action
(route의 이름)과 method
(route method) 갖는다.request.get(<key>)
에서 데이터를 가져올 때 key로 사용된다.POST
vs GET
<form action="/create" method="post">
<div>
<label for="field1">Field 1</label>
<input type="text" name="field1">
</div>
<div>
<label for="field2">Field 2</label>
<input type="text" name="field2">
</div>
<div>
<input type="submit" id="submit" value="Create" />
</div>
</form>
/create
route로 request body와 함께 전송한다.field1=value1&field2=value2
request.form.get('username')
<form action="/create" method="get">
<!--이하 동일-->
/create?field1=value&field2=value2
request.args.get('field')
POST 메소드를 사용하여 /create
route로 데이터를 전송할 때 Flask에서는 어떻게 처리해아할까?
@app.route('/create', method=['POST'] # route handler
def create():
value1 = request.form.get('field1') # 두 방법 모두 값을 받아올 수 있음
value2 = request.form['field2']
// do something with the user data ... # 받아온 값을 데이터 베이스에 추가해야함
return render_template('index.html') # 결과를 나타낼 view
이전에 만들었던 todo app이 사용자 값을 받아서 데이터베이스에 레코드를 추가할 수 있도록 변경해보자.
<html>
<head>
<title>Todo App</title>
</head>
<body>
<!-- 추가된 내용 -->
<form method="post" action="/todos/craete"> <!-- action은 보통 '/resource의 이름/수행할 action'으로 짓는다 -->
<input type="text" name="description" />
<input type="sumbit" value="Create" />
</form>
<!----------------->
<ul>
{% for d in data %}
<li>{{ d.description }}</li>
{% endfor %}
</ul>
</body>
<html>
# app.py
from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:gus123@localhost:5432/todoapp'
db = SQLAlchemy(app)
class Todo(db.Model):
__tablename__ = 'todos'
id = db.Column(db.Integer, primary_key=True)
description = db.Column(db.String(), nullable=False)
def __repr__(self):
return f'<Todo {self.id} {self.description}>'
db.create_all()
#--------------------------------------------------------
@app.route('/todos/create', methods=['POST'])
def create_todo():
description = request.form.get('description', '')
todo = Todo(description=description)
db.session.add(todo)
db.session.commit()
return redirect(url_for('index')) # index route handler
# '/todos/create' route로 description의 value를 받아온다.
# 위에서 선언한 Todo의 description에 해당 값을 추가한다.
# commit으로 데이터베이스에 반영시킨다.
# 새롭게 바뀐 index 페이지를 redirect한다.
#--------------------------------------------------------
@app.route('/')
def index():
return render_template('index.html', data = Todo.query.all())
if __name__ == '__main__':
app.run(debug=True)
View에 내용을 입력하면 Controller가 값을 받아서 Model을 조정하고 그 결과를 view가 반영할 수 있도록 한다.(MVC flow)