Flask WTForms:实现表单数据提交、后端函数处理与结果页面动态展示

Flask WTForms:实现表单数据提交、后端函数处理与结果页面动态展示

本教程将详细阐述如何在flask应用中有效整合wtforms,以构建交互式用户表单。内容涵盖了如何从表单获取用户输入、将数据传递给后端python函数进行处理、以及如何将函数返回的结果动态地呈现在网页上。教程重点强调了wtforms表单中csrf令牌的正确使用,这是确保表单提交验证成功的关键步骤,同时也是保障应用安全性的重要实践。

在构建现代web应用程序时,收集用户输入、处理这些数据并展示结果是核心功能之一。Flask作为一个轻量级的python Web框架,结合WTForms可以高效地实现这一目标。本教程将引导您完成一个示例,演示如何使用Flask和WTForms构建一个简单的表单,获取用户数据,将其传递给后端python函数进行处理,并将处理结果动态地显示在网页上。

1. 项目结构与基本配置

首先,我们假定您有一个基本的Flask项目结构,包含以下文件:

your_project/ ├── main.py               # Flask应用主文件 ├── form.py               # WTForms表单定义 ├── main_functions/       # 存放后端业务逻辑函数 │   └── get_res.py ├── templates/            # html模板文件 │   ├── base.html │   └── index.html ├── .env                  # 环境变量文件,用于存放SECRET_KEY └── requirements.txt      # 项目依赖

main.py:Flask应用初始化与配置

在main.py中,我们需要初始化Flask应用,并配置一个SECRET_KEY。SECRET_KEY对于WTForms的CSRF(跨站请求伪造)保护至关重要。

# main.py from flask import Flask, render_template, request from form import SetsForm from main_functions.get_res import get_result  import os from dotenv import load_dotenv  # 加载环境变量 load_dotenv() KEY = os.getenv("KEY")  app = Flask(__name__) # 配置SECRET_KEY,WTForms的CSRF保护依赖于此 app.config['SECRET_KEY'] = KEY  @app.route('/', methods=['GET', 'POST']) def index():     form = SetsForm()     # 初始化一个空字典用于存储结果,确保在GET请求时不会出现未定义变量错误     results = {}      # form.validate_on_submit() 会检查请求方法是否为POST,并运行所有字段的验证器     if form.validate_on_submit():         # 获取表单数据         a = form.user_a_value.data         b = form.user_b_value.data          # 调用后端函数获取结果         res_merge_a_b, res_intersection_a_b, res_difference_a_b, res_symm_diff_a_b = get_result(a, b)          # 将结果存储到字典中,方便传递给模板         results = {             'res_merge_a_b': res_merge_a_b,             'res_intersection_a_b': res_intersection_a_b,             'res_difference_a_b': res_difference_a_b,             'res_symm_diff_a_b': res_symm_diff_a_b         }         # 在控制台打印结果,用于调试         print("计算结果:", results)     else:         # 如果是GET请求或POST请求但验证失败,打印表单错误(如果有的话)         print("表单验证失败或GET请求:", form.errors)      # 统一渲染模板,无论是否提交成功,都会传递表单对象和结果(可能为空)     return render_template('index.html', form=form, **results)  if __name__ == '__main__':     app.run(debug=True)

.env文件示例

# .env KEY="your_super_secret_key_here"

2. 定义WTForms表单 (form.py)

在form.py中,我们定义一个继承自FlaskForm的表单类,包含用户输入字段和提交按钮。请注意,FlaskForm需要从flask_wtf导入。

Flask WTForms:实现表单数据提交、后端函数处理与结果页面动态展示

怪兽AI数字人

数字人短视频创作,数字人直播,实时驱动数字人

Flask WTForms:实现表单数据提交、后端函数处理与结果页面动态展示44

查看详情 Flask WTForms:实现表单数据提交、后端函数处理与结果页面动态展示

# form.py from flask_wtf import FlaskForm # 修正:原问题中缺少此导入 from wtforms import FloatField, SubmitField from wtforms.validators import DataRequired, NumberRange # 示例性添加验证器  class SetsForm(FlaskForm):     # FloatField 用于浮点数输入,并添加DataRequired验证器确保字段非空     user_a_value = FloatField('集合A的值', validators=[DataRequired("请输入集合A的值!")])     user_b_value = FloatField('集合B的值', validators=[DataRequired("请输入集合B的值!")])     user_submit_btn = SubmitField('获取结果')

3. 后端业务逻辑函数 (main_functions/get_res.py)

这个文件包含了实际执行集合操作的函数。为了教程的完整性,我们提供简化版的集合操作函数。在实际应用中,这些函数会实现更复杂的逻辑。

# main_functions/get_res.py # 假设 operations_functions 路径正确且函数已定义 # from operations_functions.a_merge_b import merge_a_b # from operations_functions.a_intersection_b import intersection_a_b # from operations_functions.a_difference_b import difference_a_b # from operations_functions.a_symmetrical_difference_b import symmetrical_difference_a_b  # 简化示例:这里直接使用Python的set操作,实际应用中可能需要更复杂的解析 def merge_a_b(a, b):     # 假设a, b是单个数字,这里模拟集合操作,实际应处理字符串输入转换为集合     return {a, b}  def intersection_a_b(a, b):     return {a} if a == b else set()  def difference_a_b(a, b):     return {a} if a != b else set()  def symmetrical_difference_a_b(a, b):     return {a, b} if a != b else set()   def get_result(a, b):     # 在实际应用中,a和b(从表单获取的可能是字符串)可能需要转换为集合类型     # 这里为了演示,假设a和b是浮点数,直接进行模拟操作     res_merge_a_b = merge_a_b(a, b)     res_intersection_a_b = intersection_a_b(a, b)     res_difference_a_b = difference_a_b(a, b)     res_symm_diff_a_b = symmetrical_difference_a_b(a, b)      # 将集合结果转换为逗号分隔的字符串,以便在HTML模板中显示     res_merge_a_b = ', '.join(str(x) for x in sorted(list(res_merge_a_b)))     res_intersection_a_b = ', '.join(str(x) for x in sorted(list(res_intersection_a_b)))     res_difference_a_b = ', '.join(str(x) for x in sorted(list(res_difference_a_b)))     res_symm_diff_a_b = ', '.join(str(x) for x in sorted(list(res_symm_diff_a_b)))      return res_merge_a_b, res_intersection_a_b, res_difference_a_b, res_symm_diff_a_b

4. 渲染页面与展示结果 (templates/index.html)

index.html负责渲染表单,并根据后端传递的数据动态显示结果。最关键的改动是在<form>标签内添加{{ form.csrf_token }},这是WTForms CSRF保护机制的一部分,如果缺少它,form.validate_on_submit()将始终返回False,导致表单数据无法被正确处理。

{% extends 'base.html' %}  {% block body %} <section class="main_section">     <div class="container">         <!-- 页面标题 -->         <div class="main_title">             <h1>输入集合元素</h1>         </div>          <!-- 表单:用户输入数据和提交按钮 -->         <form action="{{ url_for('index') }}" method="post">             <!-- 关键:添加CSRF令牌。没有它,WTForms的验证将失败! -->             {{ form.csrf_token }}              <!-- 提交按钮 -->             <div class="user_submit">                 {{ form.user_submit_btn() }} <br>             </div>              <!-- 用户数据 A -->             <div class="user_data_A">                 {{ form.user_a_value.label }}                 {{ form.user_a_value(size=30) }}                 <!-- 显示字段错误信息 -->                 {% if form.user_a_value.errors %}                     <ul class="errors">                         {% for error in form.user_a_value.errors %}                             <li>{{ error }}</li>                         {% endfor %}                     </ul>                 {% endif %}             </div>              <!-- 用户数据 B -->             <div class="user_data_B">                 {{ form.user_b_value.label }}                 {{ form.user_b_value(size=30) }}                 <!-- 显示字段错误信息 -->                 {% if form.user_b_value.errors %}                     <ul class="errors">                         {% for error in form.user_b_value.errors %}                             <li>{{ error }}</li>                         {% endfor %}                     </ul>                 {% endif %}             </div>         </form>          <!-- 结果展示区 -->         <div class="result">             <!-- 仅当后端传递了结果时才显示结果块 -->             {% if res_merge_a_b is defined %}                 <div class="result_merge">                     <h5>A ⋃ B = {{ res_merge_a_b }}</h5>                 </div>                  <div class="result_intersection">                     <h5>A ⋂ B = {{ res_intersection_a_b }}</h5>                 </div>                  <div class="result_difference">                     <h5>A  B = {{ res_difference_a_b }}</h5>                 </div>                  <div class="result_symmetrical_difference">                     <h5>A △ B = {{ res_symm_diff_a_b }}</h5>                 </div>             {% endif %}         </div>     </div> </section> {% endblock %}

base.html 示例 (如果存在)

为了确保index.html能正常工作,base.html通常包含HTML骨架和样式链接。

 <!DOCTYPE html> <html lang="zh"> <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <title>Flask WTForms

上一篇
下一篇
text=ZqhQzanResources