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

在 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'})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值