允许用户向你的网络应用提交数据是一个普遍的需求。无论你使用的是什么Web框架或解决方案,HTML表单都是通常用来收集和提交来自终端用户的数据给Web应用程序的方法。在本教程中,我们将看看如何让表单在Flask中工作,如何在Flask中获得表单数据,以及在使用Flask时如何访问各种表单字段。
在模板中添加一个表单
在页面模板中,让我们添加一些基本的标记,勾勒出一个表单。这个表单有一个URL的输入字段,一个短代码的输入字段,两个描述这些输入的标签,以及一个提交输入。
flask-tutorial/templates/home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Make A Short URL</title>
</head>
<body>
<h1>Make A Short URL</h1>
<form action="shortenurl">
<label for="url">Enter URL</label>
<input type="url" name="url" value="" required>
<label for="shortcode">Enter Name</label>
<input type="text" name="shortcode" value="" required>
<input type="submit" value="Submit">
</form>
</body>
</html>

提交表单数据
每个表单都有一个动作属性,指定表单提交到哪个URL。为了处理这个问题,我们需要在app.py中设置正确的路由。让我们修改app.py文件以反映这一点。同时,我们可以在项目中添加一个新的文件,命名为shortenurl.html,因为那是将被渲染的模板。
flask-tutorial/app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
@app.route('/shortenurl')
def shortenurl():
return render_template('shortenurl.html')

在shortenurl.html文件中,我们可以添加一些基本的标记,让用户知道他们目前在什么页面上。
flask-tutorial/templates/shortenurl.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Here Is Your URL!</title>
</head>
<body>
<h1>Here Is Your URL!</h1>
</body>
</html>
如何访问请求数据
与HTML表单相关的数据是在HTTP请求中进行的。为了在Flask中访问表单请求数据,我们可以导入request并使用request.args。
flask-tutorial/app.py
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
@app.route('/shortenurl')
def shortenurl():
return render_template('shortenurl.html', shortcode=request.args['shortcode'])
上面的代码使用request来获取中包含的数据,该数据存在于home.html中。现在,为了在表单提交后在另一个页面上显示这些数据,我们只需在Jinja模板中添加插值,我们在flask页面模板教程中探讨过。
flask-tutorial/templates/shortenurl.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Here Is Your URL!</title>
</head>
<body>
<h1>Here Is Your URL!</h1>
<h2>{{ shortcode }}</h2>
</body>
</html>
现在我们可以在表单中添加一些数据,然后点击提交。

一旦点击,目标页面模板就会显示输入到短码输入栏的值。

如何发出一个POST请求
到目前为止,代码中的管道已经到位,可以在Flask中实现基本的表单提交工作。它使用的是GET请求,这对Web表单来说不是很好。相反,我们应该让表单使用POST请求。要做到这一点,我们可以对表单和路由做一些调整。
指定表单动作
为了表明表单应该使用POST请求,我们可以在表单标签的开头添加method=post。
flask-tutorial/templates/home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Make A Short URL</title>
</head>
<body>
<h1>Make A Short URL</h1>
<form action="shortenurl" method="post">
<label for="url">Enter URL</label>
<input type="url" name="url" value="" required>
<label for="shortcode">Enter Name</label>
<input type="text" name="shortcode" value="" required>
<input type="submit" value="Submit">
</form>
</body>
</html>
接下来,我们需要在app.py的路由中修复请求类型。如果你试图在Flask中提交一个指定为POST请求的表单,而app.py不能支持,你会得到一个错误,比如。"Method Not Allowed The method is not allowed for the requested URL"。为了使路由支持POST请求,可以使用下面的高亮代码。
flask-tutorial/app.py
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
@app.route('/shortenurl', methods=['GET', 'POST'])
def shortenurl():
return render_template('shortenurl.html', shortcode=request.args['shortcode'])
request.args vs request.form
现在提交表单会产生一个错误,这并不理想。
werkzeug.exceptions.BadRequestKeyError
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'shortcode'
为了解决这个问题,我们可以在app.py中使用require.form而不是require.args。
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
@app.route('/shortenurl', methods=['GET', 'POST'])
def shortenurl():
return render_template('shortenurl.html', shortcode=request.form['shortcode'])
此时,POST请求是成功的,数据显示在屏幕上,而且在网络浏览器的URL中没有包含难看的变量。

检测请求方法
一个单一的路由可能支持一个以上的请求类型。事实上,我们上面的代码让/shortenurl路由同时支持GET和POST请求。在这样的情况下,一个常见的模式是使用Python if语句来决定如何处理请求。下面对代码的更新是检查请求方法是否是POST类型的。如果是,那么 shortenurl.html 页面模板就会被渲染,同时将其中一个输入字段的数据传递给模板。如果是GET请求,会返回一个简单的字符串,让用户知道是GET请求。如果有任何其他请求,如PUT、PATCH或DELETE,那么我们会让用户知道这个特定的路由不支持这些请求方法。
flask-tutorial/app.py
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
@app.route('/shortenurl', methods=['GET', 'POST'])
def shortenurl():
if request.method == 'POST':
return render_template('shortenurl.html', shortcode=request.form['shortcode'])
elif request.method == 'GET':
return 'A GET request was made'
else:
return 'Not a valid request method for this route'