Flask(五) 表单处理 request.form、WTForms

发布于:2025-06-27 ⋅ 阅读:(19) ⋅ 点赞:(0)

在 Flask 中,表单处理是构建 Web 应用时一个常见的需求。用于处理用户提交的数据,比如登录、注册、搜索等。

  • 基本表单处理:使用 request.form 获取表单数据,简单直接
  • 使用 Flask-WTF:结合 WTForms 进行表单处理和验证,简化表单操作。表单验证更强大,推荐用于复杂表单。
  • 表单验证:使用验证器确保表单数据的有效性。
  • 文件上传:处理文件上传和保存文件。
  • CSRF 保护:确保表单免受跨站请求伪造攻击。

1. 基本表单处理,使用 request.form(轻量)

示例一

创建 HTML 表单

templates/form.html 文件代码:

<!DOCTYPE html>
<html>
<head>
    <title>Form Example</title>
</head>
<body>
    <form action="/submit" method="post">
        <label for="name">Name:</label>
        <input type="text" id="name" name="name">
        <br>
        <label for="email">Email:</label>
        <input type="email" id="email" name="email">
        <br>
        <input type="submit" value="Submit">
    </form>
</body>
</html>

action="/submit":表单数据提交到 /submit 路径。
method="post":使用 POST 方法提交数据。

处理表单数据

app.py 文件代码:

from flask import Flask, render_template, request

app = Flask(__name__)

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

@app.route('/submit', methods=['POST'])
def submit():
    name = request.form.get('name')
    email = request.form.get('email')
    return f'Name: {name}, Email: {email}'

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

request.form.get('name')request.form.get('email'):获取提交的表单数据。

示例二

HTML 表单(login.html)

<form method="POST" action="/login">
  用户名:<input type="text" name="username"><br>
  密码:<input type="password" name="password"><br>
  <input type="submit" value="登录">
</form>

Flask 路由处理表单

from flask import Flask, request, render_template

app = Flask(__name__)

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        # 从表单中获取字段值
        username = request.form.get('username')
        password = request.form.get('password')
        return f"你提交了:{username} / {password}"
    return render_template('login.html')

2. 使用 Flask-WTF 扩展

安装

pip install flask-wtf

设置 Secret Key(CSRF 防护)

Flask-WTF 自动为表单提供 CSRF 保护。你需要配置一个密钥来启用 CSRF 保护,并在模板中包含隐藏的 CSRF 令牌。

app.config['SECRET_KEY'] = 'your-secret-key'

在模板中添加 CSRF 令牌方式

<form method="post">
    {{ form.hidden_tag() }}
    <!-- Form fields here -->
</form>

定义表单类

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired

class LoginForm(FlaskForm):
    username = StringField("用户名", validators=[DataRequired()])
    password = PasswordField("密码", validators=[DataRequired()])
    submit = SubmitField("登录")

HTML 模板(login.html)

<form method="POST">
  {{ form.hidden_tag() }}
  {{ form.username.label }} {{ form.username() }}<br>
  {{ form.password.label }} {{ form.password() }}<br>
  {{ form.submit() }}
</form>

{{ form.hidden_tag() }}:生成隐藏字段,用于保护表单免受 CSRF 攻击。
{{ form.name.label }}{{ form.name(size=32) }}:渲染表单字段及其标签。

Flask 视图函数

from flask import render_template
from forms import LoginForm  # 假设你表单类定义在 forms.py

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        username = form.username.data
        password = form.password.data
        return f"成功提交:{username} / {password}"
    return render_template('login.html', form=form)

validate_on_submit:检查是否是POST请求并且验证通过

✅ 常用字段类型(WTForms)

字段 含义
StringField 文本输入框
PasswordField 密码框
SubmitField 提交按钮
TextAreaField 多行输入框
SelectField 下拉选择
BooleanField 复选框

✅ 常用验证器(validators)

验证器 说明
DataRequired() 必填
Length(min, max) 长度限制
Email() 邮箱格式验证
EqualTo() 两次输入一致,比较两个字段的值(如密码确认)
NumberRange 验证数字范围
Regexp 使用正则表达式验证
URL 验证 URL
from wtforms import Form, StringField, EmailField, SubmitField
from wtforms.validators import DataRequired, Email, Length

class MyForm(FlaskForm):
    name = StringField('Name', validators=[
        DataRequired(), Length(min=1, max=50)
    ])
    email = EmailField('Email', validators=[
        DataRequired(), Email()
    ])
    password = PasswordField('密码', validators=[DataRequired()])
    confirm_password = PasswordField('确认密码', 
                                   validators=[DataRequired(), EqualTo('password')])
    submit = SubmitField('Submit')

HTML 表单字段中的 URL 验证器

用于 字段的前端验证:

<form>
  <input type="url" name="website" required placeholder="请输入网址">
  <input type="submit">
</form>

浏览器会自动验证用户输入的内容是否是合法 URL,例如 https://example.com。

总结

用法 特点
request.form 简单、快速,小项目 OK
Flask-WTF 自动验证、安全性高、大项目推荐

3.文件上传

Flask 还支持处理文件上传。上传的文件可以通过 request.files 访问。
创建文件上传表单

当你在表单中使用了 <input type="file"> 进行文件上传时,必须设置表单的 enctype 属性,如果 没有指定
enctype="multipart/form-data",那么上传的文件内容不会正确发送到服务器。

templates/upload.html 文件代码:

<!DOCTYPE html>
<html>
<head>
    <title>Upload File</title>
</head>
<body>
    <form action="/upload" method="post" enctype="multipart/form-data">
        <label for="file">File:</label>
        <input type="file" id="file" name="file">
        <br>
        <input type="submit" value="Upload">
    </form>
</body>
</html>

enctype="multipart/form-data":指定表单数据的编码类型,支持文件上传。

enctype 说明
application/x-www-form-urlencoded 默认值。适用于普通表单字段(文本、数字等)。
multipart/form-data 用于上传文件(或含文件字段的表单)。
text/plain 不常用,仅调试用途(不编码特殊字符,不推荐用于实际表单提交)。

4.处理文件上传

app.py 文件代码:

from flask import Flask, request, redirect, url_for

app = Flask(__name__)
app.secret_key = 'your_secret_key'

@app.route('/upload', methods=['POST'])
def upload():
    file = request.files.get('file')
    if file:
        filename = file.filename
        file.save(f'uploads/{filename}')
        return f'File uploaded successfully: {filename}'
    return 'No file uploaded'

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

request.files.get('file'):获取上传的文件对象。
file.save(f'uploads/{filename}'):将文件保存到指定目录。

确保创建上传目录并配置上传路径:

app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 限制为16MB

5.AJAX 表单处理

@app.route('/api/submit', methods=['POST'])
def api_submit():
    if request.is_json:
        data = request.get_json()
        # 处理数据
        return jsonify({'status': 'success'})
    return jsonify({'status': 'error', 'message': 'Invalid request'})

网站公告

今日签到

点亮在社区的每一天
去签到