FlaskForm详解

FlaskForm,是Flask框架中的一个表单处理扩展,它可以帮我们更方便地管理表单,实现表单验证、提交等功能,减轻了我们的工作压力。本文从多个方面对FlaskForm做详细的阐述,以便读者更好地理解与使用它。

一、FlaskForm二级联动

在我们的Web应用中,常常需要进行二级联动功能的实现,比如省、市、区的地址选择,或者是商品类型、子类的选择等等。使用FlaskForm可以很方便地实现这样的功能。

首先我们需要定义表单类,下面是一个例子:

from wtforms import SelectField, Form, validators
 
choices_a = [("", "请选择..."), ("1", "选项1"), ("2", "选项2"), ("3", "选项3"), ("4", "选项4")]
choices_b = [("", "请选择..."), ("a", "选项A"), ("b", "选项B"), ("c", "选项C"), ("d", "选项D")]
 
class TestForm(Form):
    select_a = SelectField("级别1", choices=choices_a, validators=[validators.DataRequired()])
    select_b = SelectField("级别2", choices=choices_b, validators=[validators.DataRequired()])

接下来,我们需要在视图函数中使用这个表单类。在GET请求中,我们需要传递一个空的表单实例到前端,让用户进行选择;在POST请求中,我们需要对用户选择的数据进行处理并返回结果。

from flask import render_template, request
 
@app.route("/double_select", methods=["GET", "POST"])
def double_select():
    form = TestForm(request.form)
 
    if request.method == "POST" and form.validate():
        select_a = form.select_a.data
        select_b = form.select_b.data
 
        # 处理选项数据...
 
        return "success"
 
    return render_template("double_select.html", form=form)

在前端模板中,我们需要利用FlaskForm提供的表单插件来渲染二级联动的功能。下面是一个例子:

<form method="post" action="">
    {{ form.select_a.label }} {{ form.select_a }}
    {{ form.select_b.label }} {{ form.select_b }}
    <input type="submit" value="提交">
</form>
{{ form.hidden_tag() }}
 
...
 
<script>
$(function() {
    $("#select_a").on("change", function() {
        $.get("/get_select_b", {"select_a": $(this).val()}, function(data) {
            var optionsHtml = "";
            $.each(data, function(key, value) {
                optionsHtml += "<option value='" + key + "'>" + value + "</option>";
            });
            $("#select_b").html(optionsHtml);
        }, "json");
    });
});
</script>

在这个例子中,我们使用了flask_wtf插件来渲染表单,使用了jQuery库来实现异步加载子类选项数据的功能。

二、FlaskForm CSRF

在我们的Web应用中,跨站请求伪造(CSRF)是一种常见的安全漏洞,攻击者可以通过构造恶意请求来实现用户信息、资金等的窃取或者篡改。使用FlaskForm提供的CSRF保护可以很好地防御这种安全漏洞。

在Flask中,我们可以通过在FlaskForm实例中设置SECRET_KEY来启用CSRF保护。下面是一个例子:

from flask_wtf.csrf import CSRFProtect
 
app = Flask(__name__)
app.config["SECRET_KEY"] = "your-secret-key"
csrf = CSRFProtect(app)

这里我们设置了一个随机的SECRET_KEY,用来加密和验证TOKEN,保证应用的安全性。然后我们使用CSRFProtect包装我们的Flask应用来启用CSRF保护。

启用CSRF保护后,我们需要在前端模板中使用FlaskForm提供的表单插件来渲染form标签,其中包含了_csrf_token的隐藏字段。下面是一个例子:

<form method="post" action="">
    {{ form.username.label }} {{ form.username }}
    {{ form.password.label }} {{ form.password }}
    <input type="submit" value="提交">
</form>
{{ form.hidden_tag() }}

当我们在POST请求中提交表单数据时,FlaskForm会自动从表单数据中获取_csrf_token字段,并且与其中包含的加密签名进行比较验证,如果验证失败则抛出异常。

三、FlaskForm联合查询

在我们的Web应用中,常常需要实现复杂的联合查询功能,比如商品名称、类型、价格的多条件组合查询等等。使用FlaskForm可以很方便地实现这样的功能。

FlaskForm提供了各种表单字段类型来方便我们实现多条件查询,比如StringField、SelectField、DateField等。下面是一个例子:

from flask_wtf import FlaskForm
from wtforms import StringField, SelectField, DateField
from wtforms.validators import DataRequired
 
class QueryForm(FlaskForm):
    name = StringField("名称")
    category = SelectField("分类", choices=[("all", "全部"), ("1", "分类1"), ("2", "分类2")])
    price_min = StringField("最小价格")
    price_max = StringField("最大价格")
    create_time = DateField("创建日期", format="%Y-%m-%d")
    update_time = DateField("更新日期", format="%Y-%m-%d")

在视图函数中,我们使用这个表单类来接收并且处理用户提交的查询条件。下面是一个例子:

@app.route("/query", methods=["GET", "POST"])
def query():
    form = QueryForm(request.form)
 
    if request.method == "POST" and form.validate():
        name = form.name.data.strip() or None
        category = form.category.data
        if category == "all":
            category = None
 
        try:
            price_min = float(form.price_min.data.strip())
        except:
            price_min = None
 
        try:
            price_max = float(form.price_max.data.strip())
        except:
            price_max = None
 
        create_time = form.create_time.data or None
        update_time = form.update_time.data or None
 
        # 处理查询条件...
 
        return "success"
 
    return render_template("query.html", form=form)

在前端模板中,我们可以使用FlaskForm提供的表单插件来渲染表单。下面是一个例子:

<form method="post" action="">
    {{ form.name.label }} {{ form.name }}
    {{ form.category.label }} {{ form.category }}
    {{ form.price_min.label }} {{ form.price_min }}
    {{ form.price_max.label }} {{ form.price_max }}
    {{ form.create_time.label }} {{ form.create_time }}
    {{ form.update_time.label }} {{ form.update_time }}
    <input type="submit" value="查询">
</form>
{{ form.hidden_tag() }}

四、FlaskForm CSRF取消

在某些情况下,我们可能需要在特定表单中取消FlaskForm的CSRF保护,比如在我们需要让用户在不登录的情况下进行某些操作的时候。FlaskForm提供了一个@csrf_exempt装饰器来完成这个功能。

在视图函数中,我们只需要在函数上方加上@csrf_exempt装饰器即可取消FlaskForm的CSRF保护。下面是一个例子:

from flask_wtf.csrf import csrf_exempt
 
@app.route("/some_action", methods=["POST"])
@csrf_exempt
def some_action():
    # 处理不需要CSRF保护的操作...
    return "success"

五、FlaskForm Python三级联动

除了常见的二级联动,有些特定的业务场景可能需要实现三级或者更多级联动的功能。FlaskForm同样可以很方便地实现这些功能。

在实现三级联动的时候,我们需要使用三个FlaskForm实例来分别表示三个下拉框。下面是一个例子:

from wtforms import Form, SelectField
 
class SelectAForm(Form):
    select_a = SelectField("级别1")
 
class SelectBForm(Form):
    select_b = SelectField("级别2")
 
class SelectCForm(Form):
    select_c = SelectField("级别3")

然后我们需要在视图函数中使用这三个表单来实现三级联动。在GET请求中,我们需要传递一族空表单到前端;在POST请求中,我们需要处理用户的选择,并且动态返回下一级的选项。下面是一个例子:

@app.route('/three_levels')
def three_levels():
    select_a_form = SelectAForm()
    select_b_form = SelectBForm()
    select_c_form = SelectCForm()
 
    return render_template("three_levels.html", select_a_form=select_a_form, select_b_form=select_b_form, select_c_form=select_c_form)
 
@app.route("/get_b")
def get_b():
    select_b_form = SelectBForm()
    id = request.args.get("id", 0, type=int)
 
    if id == 1:
        select_b_form.select_b.choices = [("", "选择..."), (1, "选项1"), (2, "选项2"), (3, "选项3")]
    elif id == 2:
        select_b_form.select_b.choices = [("", "选择..."), (4, "选项4"), (5, "选项5"), (6, "选项6")]
    elif id == 3:
        select_b_form.select_b.choices = [("", "选择..."), (7, "选项7"), (8, "选项8"), (9, "选项9")]
 
    return jsonify(select_b_form.select_b.choices)
 
@app.route("/get_c")
def get_c():
    select_c_form = SelectCForm()
    id = request.args.get("id", 0, type=int)
 
    if id == 1:
        select_c_form.select_c.choices = [("", "选择..."), (1, "选项1"), (2, "选项2"), (3, "选项3")]
    elif id == 2:
        select_c_form.select_c.choices = [("", "选择..."), (4, "选项4"), (5, "选项5"), (6, "选项6")]
    elif id == 3:
        select_c_form.select_c.choices = [("", "选择..."), (7, "选项7"), (8, "选项8"), (9, "选项9")]
 
    return jsonify(select_c_form.select_c.choices)

在前端模板中,我们需要利用FlaskForm提供的表单插件来渲染三个下拉框。其中第一级会触发AJAX请求,返回第二级的选项;第二级会触发AJAX请求,返回第三级的选项。下面是一个例子:

<form>
{{ select_a_form.select_a.label }} {{ select_a_form.select_a }}
{{ select_b_form.select_b.label }} {{ select_b_form.select_b }}
{{ select_c_form.select_c.label }} {{ select_c_form.select_c }}
</form>

<script>
$(function() {
$("#select_a").on("change", function() {
var id = $(this).val();
if (id) {
$.get("/get_b", {"id": id}, function(data) {
var optionsHtml = "<option value=''>-</option>";
$.each(data, function(key, value) {
optionsHtml += "<option value='" + key + "'>" + value + "</option>";
});
$("#select_b").html(optionsHtml).change();
}, "json");
} else {
$("#select_b").html("<option value=''>-</option>");
$("#select_c").html("<option value=''>-</option>");
}
});

原创文章,作者:ZQSQ,如若转载,请注明出处:https://www.506064.com/n/138098.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
ZQSQ的头像ZQSQ
上一篇 2024-10-04 00:18
下一篇 2024-10-04 00:19

相关推荐

  • 神经网络代码详解

    神经网络作为一种人工智能技术,被广泛应用于语音识别、图像识别、自然语言处理等领域。而神经网络的模型编写,离不开代码。本文将从多个方面详细阐述神经网络模型编写的代码技术。 一、神经网…

    编程 2025-04-25
  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25
  • Python安装OS库详解

    一、OS简介 OS库是Python标准库的一部分,它提供了跨平台的操作系统功能,使得Python可以进行文件操作、进程管理、环境变量读取等系统级操作。 OS库中包含了大量的文件和目…

    编程 2025-04-25
  • Java BigDecimal 精度详解

    一、基础概念 Java BigDecimal 是一个用于高精度计算的类。普通的 double 或 float 类型只能精确表示有限的数字,而对于需要高精度计算的场景,BigDeci…

    编程 2025-04-25
  • Python输入输出详解

    一、文件读写 Python中文件的读写操作是必不可少的基本技能之一。读写文件分别使用open()函数中的’r’和’w’参数,读取文件…

    编程 2025-04-25
  • 详解eclipse设置

    一、安装与基础设置 1、下载eclipse并进行安装。 2、打开eclipse,选择对应的工作空间路径。 File -> Switch Workspace -> [选择…

    编程 2025-04-25
  • Linux修改文件名命令详解

    在Linux系统中,修改文件名是一个很常见的操作。Linux提供了多种方式来修改文件名,这篇文章将介绍Linux修改文件名的详细操作。 一、mv命令 mv命令是Linux下的常用命…

    编程 2025-04-25
  • C语言贪吃蛇详解

    一、数据结构和算法 C语言贪吃蛇主要运用了以下数据结构和算法: 1. 链表 typedef struct body { int x; int y; struct body *nex…

    编程 2025-04-25
  • MPU6050工作原理详解

    一、什么是MPU6050 MPU6050是一种六轴惯性传感器,能够同时测量加速度和角速度。它由三个传感器组成:一个三轴加速度计和一个三轴陀螺仪。这个组合提供了非常精细的姿态解算,其…

    编程 2025-04-25
  • nginx与apache应用开发详解

    一、概述 nginx和apache都是常见的web服务器。nginx是一个高性能的反向代理web服务器,将负载均衡和缓存集成在了一起,可以动静分离。apache是一个可扩展的web…

    编程 2025-04-25

发表回复

登录后才能评论