Flask简介:
Flask是一个用Python编写的小而强大的Web应用框架。它被设计为易于扩展的轻量级框架,正如其官网所说:“微型”不意味着您的整个Web应用必须放在单个Python文件中(虽然它确实可以),也不意味着Flask缺乏功能。相反,”微型“意味着Flask默认情况下保持核心简单但可扩展。
以下是Flask的一些关键特性:
开发服务器和调试器: Flask内置了一个开发服务器和一个交互式调试器。当您在开发模式下运行您的应用时,Flask会为您提供一个本地服务器,当您的代码更改时它会重新加载,并且当出错时提供一个有用的调试器。
集成单元测试支持: Flask支持单元测试,这意味着您可以使用Python的内置unittest库来编写测试,确保您的应用按预期工作。
RESTful请求分发: 使用Flask,您可以通过路由器将请求映射到Python函数上,这是创建RESTful应用的基础。
使用Jinja2模板引擎: Flask使用Jinja2模板引擎来动态构建前端。Jinja2是一个功能强大的模板引擎,它允许您在服务器端创建HTML模板,然后填入动态数据来呈现页面。
支持安全的Cookies(会话): Flask可以储存和操纵用户会话数据。它也处理Cookies和数据的安全性,比如通过签名来防止用户篡改Cookies中存储的数据。
Unicode基础: Flask 基于Unicode,使它处理国际化和本地化编码变得容易。
扩展性: Flask拥有一个被动的扩展框架,借助该框架第三方开发者能够很容易地为Flask添加新功能,比如ORM、表单验证、文件上传处理、各种开放式身份验证技术等。
WSGI 1.0兼容: Flask实现了WSGI协议,这是Python中应用于服务器和应用交互的标准接口。
基于Werkzeug和Jinja2: Flask 依赖于 Werkzeug WSGI工具集和Jinja2模板引擎,这些都是用Python编写的Pocco项目的一部分。
为什么学习Flask:
简单易学: Flask 有一个简单直观的 API,它允许开发者快速上手。即使是没有太多Web开发背景的人也能轻松理解基本概念并开始构建Web应用。
灵活性高: Flask 几乎不做任何假设关于您项目的怎样结构,这就给了您巨大的灵活性来组织您的应用如何执行任务。您可以选择自己的工具和库来完成任务,这是大型框架如 Django 那种 “全包” 方法所无法提供的。
微服务友好: Flask 的轻量级特性使其成为构建微服务架构的理想选择。每个服务可以是一个小型的 Flask 应用,独立地开发和部署,从而提升可伸缩性和维护性。
强大的扩展库: 虽然 Flask 本身很简单,但通过丰富的扩展库,开发者可以轻松地添加各种功能,包括用户认证、数据库集成、表单验证、上传管理等。
社区支持: Flask 有一个非常活跃的社区和较多的文档。如果遇到任何问题,通常都能在社区或者Stack Overflow上找到答案。
成熟稳定: Flask 自2004年推出以来,经过多年的开发,目前已经非常成熟和稳定,许多公司和项目依赖于它的生产。
快速开发: Flask 使搭建原型和迭代快速发生,你可以快速地从一个基础项目构建到一个完整功能的应用。
透明性: Flask的代码库相比其他框架来说比较简单,这使得其工作方式更加透明,也更容易理解其内部机制。
教育资源丰富: 存在大量针对 Flask 的教程、指南和实例项目,这为学习提供了极大的便利性。
适应不同规模的项目: 无论是小型的个人项目还是大型公司级应用,Flask 都可以胜任。
总的来说,Flask 提供了一个简单、灵活且功能强大的平台,使得Web开发变得既可控又高效。学习 Flask 能够让开发者在Web领域获得一项重要的技能,并且有助于构建可维护和可扩展的应用产品。
Jinja2在Flask中的作用:
模板渲染: Jinja2 允许您创建包含动态内容的 HTML 模板。在 Flask 中,您可以使用 Jinja2 渲染模板并将数据传递给模板,然后生成最终的 HTML 页面。这使得开发 Web 应用程序变得更加灵活和易于维护。
模板继承: Jinja2 支持模板继承,这是一种重用模板代码并在不同页面中共享相同布局的强大技术。通过使用模板继承,您可以在 Flask 中创建具有一致性布局的网站,并更轻松地对布局进行更改和更新。
模板变量: Jinja2 允许您在模板中使用变量来动态显示数据。在 Flask 中,您可以在视图函数中将数据传递给模板,并在模板中使用这些数据来呈现页面内容。
模板控制结构: Jinja2 支持丰富的控制结构,如条件语句、循环语句和过滤器等。这些控制结构使您能够在模板中进行逻辑判断和数据处理,从而实现更复杂的页面逻辑。
安全过滤: Jinja2 提供了安全过滤器和自动转义功能,可以帮助您防止跨站脚本(XSS)等安全问题。这使得在 Flask 中开发安全的 Web 应用程序变得更加容易。
第一部分:Flask 概述
一. Flask的基础知识和特点:
微框架: Flask 被称为微框架,主要是因为它的核心非常简单,但功能可以通过插件无限扩展。
WSGI 兼容: Flask 实现了 WSGI (Web Server Gateway Interface) 服务器与应用程序接口的规范,允许它与多种实现该协议的服务器配合工作。
路由系统: Flask 提供了一个强大的 URL 路由系统,可以使用装饰器在视图函数上建立路由,方便定义 URL 规则。
模板引擎: Flask 使用 Jinja2 作为模板引擎,它支持条件语句、循环、过滤器、宏等高级功能,帮助在服务器端生成动态 HTML 内容。
集成开发服务器和调试器: Flask 自带了一个开发服务器,以及一个交互式的调试器。这意味着,在开发过程中,如果代码出现错误,可以在浏览器中直接交互地追踪问题。
单元测试支持: Flask 支持扩展单元测试以确保应用的稳定性,它允许为应用编写和运行测试用例,确保代码质量。
请求分发: Flask 可以处理 Web 请求并作出响应,允许开发者编写视图函数来响应不同的 HTTP 请求。
插件和扩展: 虽然 Flask 本身很“小”,但它支持使用扩展来添加新功能,如 ORM、表单验证、用户认证等,这加强了其适应不同项目需求的能力。
轻量和灵活: Flask 本身代码量小,不强制要求项目布局或是依赖,这赋予开发者高度的灵活性,可以按项目的具体需求来选择工具和库。
易于理解和上手: Flask 的简单性还体现在其代码的可阅读性以及文档的完备性上,使得其非常适合初学者学习和使用。
二. Flask 适用于哪些类型的项目:
小型项目和原型开发: Flask 的简洁性和灵活性使其非常适合用于小型项目和原型开发。如果您需要快速地构建一个简单的 Web 应用程序或原型来验证概念,Flask 是一个不错的选择。
API 服务: Flask 可以作为构建 RESTful API 服务的工具。它支持路由、请求处理、数据序列化等功能,使得开发 API 变得简单和高效。
微服务架构: Flask 在微服务架构中也表现出色。您可以使用 Flask 快速构建独立的微服务,并通过 HTTP 或其他协议进行通信,从而实现系统的分布式和模块化。
学习和教学: 由于 Flask 的简单性和易学性,它常被用于学习 Python Web 开发和教学。对于初学者来说,使用 Flask 可以快速上手,并且能够了解 Web 开发的基本概念和技术。
Web 应用程序的快速原型和开发: 对于需要快速原型开发或者对时间敏感的项目,Flask 是一个理想的选择。它不需要大量的配置和学习成本,可以让开发者快速构建出具有基本功能的 Web 应用程序。
自定义和定制性强的项目: Flask 的设计理念是简单而灵活,它提供了很多自定义和扩展的接口,使得开发者可以根据项目需求进行灵活的定制和扩展。
虽然 Flask 适用于许多类型的项目,但对于大型、复杂的企业级应用程序,可能需要考虑使用更完整、功能更丰富的框架,如 Django。Flask 更适合于小规模、中小型的项目以及快速开发和原型验证。
三.Flask 的优势和局限性
优势:
轻量级和简单易学: Flask 的设计理念是简单和轻量级,没有过多的依赖和复杂性,因此易于学习和上手。
灵活性: Flask 提供了很高的灵活性,您可以根据项目需求自由选择和组合需要的功能,不受框架限制。
模块化: Flask 支持模块化开发,可以轻松地将应用程序拆分为不同的模块或者添加额外的功能模块。
集成度高: Flask 可以与其他 Python 库和工具很好地集成,如 SQLAlchemy、WTForms、Jinja2 等,使得开发更加便利。
RESTful API 支持: Flask 提供了很好的支持来构建 RESTful API 服务,可以快速开发和部署 API 接口。
社区活跃: Flask 拥有一个活跃的社区,有大量的插件和扩展可供选择,可以帮助开发者加速开发过程。
局限性:
过于简洁: 有时候,Flask 的简洁和灵活性也可能成为一种限制,对于大型、复杂的应用程序可能需要自行添加一些功能或者扩展,增加开发成本和工作量。
缺少内置功能: 相比于其他 Web 框架如 Django,Flask 在一些方面缺少内置功能,需要依赖第三方插件或者自行实现。
自由度带来的责任: Flask 的灵活性也意味着开发者需要自行做出许多决策,包括项目结构、安全性、数据库选型等,这可能增加了开发者的责任和工作量。
不适合大规模项目: 尽管 Flask 可以用于大型项目,但对于复杂度较高、团队规模较大的企业级项目,可能需要更完整和功能更丰富的框架来满足需求。
第二部分:设置开发环境
四.环境搭建以及新手入门
创建虚拟环境(可选): 首先,您可以选择在 Anaconda 中创建一个新的虚拟环境来安装 Flask,以隔离不同项目的依赖。可以使用以下命令创建虚拟环境,其中myenv
是环境名称,您可以自行替换为喜欢的名称。 conda create -n myenv python=3.8.15
激活虚拟环境: 激活刚刚创建的虚拟环境,命令如下: conda activate myenv
安装 Flask: 在虚拟环境中,使用 pip 命令安装 Flask 和相关依赖: pip install flask
安装其他依赖(可选): 如果您的项目需要其他依赖,比如数据库驱动、表单处理等,可以继续使用 pip 安装相应的依赖包,例如: pip install flask_sqlalchemy flask_wtf
上述命令安装了 Flask SQLAlchemy(用于数据库操作)和 Flask WTF(用于表单处理)等常用扩展。
验证安装: 安装完成后,可以验证 Flask 是否安装成功。创建一个简单的 Python 脚本,例如app.py
,并编写一个最基本的 Flask 应用程序: from flask import Flaskapp = Flask(__name__)@app.route('/')def hello_world(): return 'Hello, Flask!'if __name__ == '__main__': app.run(debug=True)
运行应用程序: 在命令行中切换到保存了 app.py
的目录,并执行以下命令来运行应用程序: python app.py
应用程序将会运行在本地服务器上,并在终端显示类似于 Running on http://127.0.0.1:5000/
的信息。打开浏览器并访问该地址,您应该能够看到 "Hello, Flask!" 的消息。
第三部分:理解 Flask 的路由
五. Flask路由
Flask 的路由系统使得 Web 应用可以响应特定的 URL,每个路由映射到一个 Python 函数。定义路由的方式很直接,一般通过应用实例上的 route()
装饰器和相应的视图函数来完成。
# 首先,需要从 flask 模块导入 Flask 类来创建应用实例from flask import Flask# 创建 Flask 应用实例。Flask 类的实例将会是我们的 WSGI 应用app = Flask(__name__)# 使用 app.route 装饰器定义基本路由。# 当客户端访问网站根目录即 / 时,会调用这个视图函数@app.route('/')def index(): return 'Welcome to my Flask app!'# Flask 能够通过在 URL 中包含特定的变量部分来支持变量规则。# 使用尖括号(<variable_name>)标记动态部分,它将作为关键字参数传递给与规则相关联的函数@app.route('/hello/<name>')def hello(name): # 在这个视图函数中,可以使用变量 name 来响应 URL return f'Hello, {name}!'# 可以创建带有多个动态部分的 URL 规则,并以不同类型转换变量值@app.route('/post/<int:post_id>')def show_post(post_id): # post_id 的类型会自动地由 string 转换成 int return f'Post ID is {post_id}'# 可以为一个视图函数绑定多个 URL,这样可以提供多种不同的路径映射到同一页面@app.route('/about')@app.route('/about-us')def about(): return 'This is the about page.'# 最后,需要检查是直接运行此脚本还是通过其他方式调用的脚本。# 如果是直接运行,则启动 Flask 的开发服务器if __name__ == '__main__': app.run(debug=True) # 启用调试模式,服务器会在代码修改后自动重启,并在发生错误时提供调试信息
以上代码展示了 Flask 的基础路由定义:
使用 @app.route()
装饰器来告知 Flask 哪个 URL 应当触发我们的函数。
动态地从 URL 中捕获值。
可以为变量部分指定一个可选的转换器来指定它的类型。
一个视图函数可以绑定到多个路由。
六. URL 构建函数
在 Flask 中,URL 构建函数是一个非常有用的工具,用于构建动态生成的 URL。它可以帮助您在视图函数中动态生成 URL,而不必硬编码 URL 地址,这样可以提高代码的可维护性和灵活性。Flask 提供了 url_for()
函数来进行 URL 构建。
1. url_for()
函数的基本用法:
from flask import Flask, url_forapp = Flask(__name__)@app.route('/')def index(): # 使用 url_for() 构建路由 user_profile_url = url_for('show_user_profile', username='john') return f'The URL for user profile is: {user_profile_url}'@app.route('/user/<username>')def show_user_profile(username): return f'User: {username}'if __name__ == '__main__': app.run(debug=True)
在上述示例中,url_for()
函数用于构建名为 show_user_profile
的视图函数的 URL。在 index()
视图函数中,调用 url_for('show_user_profile', username='john')
将生成动态 URL /user/john
,然后将该 URL 返回给用户。
2. 构建静态资源 URL:
url_for()
函数不仅可以构建动态路由的 URL,还可以用于构建静态资源的 URL,如 CSS 文件、JavaScript 文件或者图片等。示例如下:
from flask import Flask, url_forapp = Flask(__name__)@app.route('/')def index(): # 使用 url_for() 构建静态资源的 URL css_url = url_for('static', filename='styles.css') js_url = url_for('static', filename='scripts.js') return f'The CSS URL is: {css_url}<br>The JavaScript URL is: {js_url}'if __name__ == '__main__': app.run(debug=True)
在这个示例中,url_for('static', filename='styles.css')
和 url_for('static', filename='scripts.js')
分别构建了静态 CSS 和 JavaScript 文件的 URL,这些文件位于 Flask 应用程序的 static
目录下。
3. 参数和默认值:
url_for()
函数的第一个参数是视图函数的名称,后面可以跟着动态路由参数,例如 username='john'
。如果视图函数接受多个参数,可以依次列出。另外,您也可以在路由中定义默认值,这样在构建 URL 时如果没有传入参数,将使用默认值。
第四部分:模板与 Jinja2 介绍
七. Jinja2与Flask的关系
Jinja2 是一个功能强大的模板引擎,主要用于生成动态内容的 HTML 页面。它与 Flask 之间有着密切的关系,因为 Flask 默认使用 Jinja2 作为模板引擎来渲染页面。
1. Jinja2 的特点和功能:
模板继承: Jinja2 支持模板继承,使得可以定义一个基础模板,并在其他模板中继承和扩展这个基础模板,实现页面布局的复用和共享。
模板变量: 可以在模板中使用变量来动态显示数据,例如从 Flask 视图函数传递的数据可以在模板中渲染。
控制结构: 支持条件语句、循环语句等控制结构,使得可以在模板中进行逻辑判断和数据处理。
过滤器: 提供了丰富的过滤器,可以对数据进行格式化、处理和过滤,例如日期格式化、字符串处理等。
安全性: 自带自动转义功能,可以防止跨站点脚本(XSS)攻击,提高页面安全性。
2. Flask 中的 Jinja2:
Flask 使用 Jinja2 作为默认的模板引擎,这意味着在 Flask 中开发 Web 应用程序时,您可以直接使用 Jinja2 来渲染模板并生成 HTML 页面。Flask 提供了与 Jinja2 集成的功能,使得在 Flask 视图函数中渲染模板变得非常简单。
3. Flask 中使用 Jinja2:
在 Flask 中使用 Jinja2 主要涉及两个方面:
模板文件: 在 Flask 项目的 templates
目录中编写 Jinja2 模板文件,这些模板文件通常使用 .html
或 .jinja2
扩展名。
视图函数: 在 Flask 的视图函数中使用 render_template()
函数来渲染模板并将数据传递给模板,例如:
from flask import Flask, render_templateapp = Flask(__name__)@app.route('/')def index(): username = 'John Doe' return render_template('index.html', username=username)
在上述示例中,render_template()
函数用于渲染名为 index.html
的模板,并传递 username
变量给模板,模板可以使用这个变量来生成动态内容。
八. Jinja2的基本语法(变量、控制结构、继承、过滤器)
1. 变量:
Jinja2 中的变量用 {{ 变量名 }}
来表示,可以在模板中使用变量来动态显示数据。例如:
<p>Hello, {{ name }}</p>
# Flask中将变量传递给模板from flask import Flask, render_templateapp = Flask(__name__)# 也可指定模板目录# app = Flask(__name__, template_folder="/opt/python-projects/flask")@app.route('/')def hello(): name = "MichaelxcT" return render_template('hello.html', name=name)if __name__ == '__main__': app.run(host='0.0.0.0', port=8000, debug=True)
在上面的示例中,{{ name }}
是一个变量,它将根据传递给模板的值来动态渲染。
2. 控制结构:
Jinja2 提供了丰富的控制结构,包括条件语句、循环语句等,用于在模板中进行逻辑判断和数据处理。以下是一些常见的控制结构:
条件语句: 使用{% if 条件 %}...{% endif %}
来实现条件判断,例如: <!-- if.html模板 --><!DOCTYPE html><html><head> <title>Hello</title></head><body> {% if user %} {% if user.age >= 18 %} <h1>Hello {{ user.name }}, you are an adult!</h1> {% else %} <h1>Hello {{ user.name }}, you are a minor!</h1> {% endif %} {% else %} <h1>Hello, anonymous user!</h1> {% endif %}</body></html>
# if.py# Flask中使用if控制结构from flask import Flask, render_templateapp = Flask(__name__)@app.route('/')def hello(): user = {"name": "MichaelxcT", "age": 22} return render_template('if.html', user=user)if __name__ == '__main__': app.run(host='0.0.0.0', port=8000, debug=True)
在上面的示例中,使用if语句来控制输出,根据用户的年龄显示不同的消息。
循环语句: 使用{% for 变量 in 列表 %}...{% endfor %}
来实现循环,例如: <!-- for.html模板 --><!DOCTYPE html><html><head> <title>Hello</title></head><body> {% for user in users %} <h1>Hello {{ user.name }}!</h1> <p>You are {{ user.age }} years old.</p> {% endfor %}</body></html>
# for.py# Flask中使用for循环结构from flask import Flask, render_templateapp = Flask(__name__)@app.route('/')def hello(): users = [{"name": "MichaelxcT", "age": 22}, {"name": "zhangsan", "age": 30}] return render_template('for.html', users=users)if __name__ == '__main__': app.run(host='0.0.0.0', port=8000, debug=True)
在上面的示例中,使用 for
循环来遍历用户列表,并输出每个用户的信息。
3. 继承:
Jinja2 支持模板继承,可以定义一个基础模板,并在其他模板中继承和扩展这个基础模板。使用 {% extends 'base.html' %}
来继承模板,使用 {% block %}...{% endblock %}
来定义块并覆盖基础模板中的内容。例如:
基础模板 base.html
:
<!DOCTYPE html><html><head> <title>{% block title %}My Website{% endblock %}</title></head><body> {% block content %}{% endblock %}</body></html>
继承基础模板并扩展内容的子模板:
<!-- base.html模板 --><!DOCTYPE html><html><head> <title>{% block title %}{% endblock %}</title></head><body> {% block content %}{% endblock %}</body></html>
<!-- extend.html模板 -->{% extends "base.html" %}{% block title %}Hello{% endblock %}{% block content %} <h1>Hello World!</h1>{% endblock %}
# extend.py# Flask中使用继承from flask import Flask, render_templateapp = Flask(__name__)@app.route('/')def hello(): return render_template('extend.html')if __name__ == '__main__': app.run(host='0.0.0.0', port=8000, debug=True)
在上面的示例中,定义了一个名为 base.html
的模板,并在 extend.html
模板中继承了该模板。extend.html
模板中可以重写 base.html
模板中的块,并在其中添加新的内容。
4.过滤器:
过滤器在 Jinja2 中用于对变量内容进行转换和格式化。过滤器通过管道符号(|
)应用到变量上,可以单独使用或串联使用,允许你对输出进行链式转换。以下是一些内置过滤器的例子及自定义过滤器的编写方法。
常用的内置过滤器:
safe
:禁用自动的字符串转义。
capitalize
:把字符串的首字母转换为大写,其余字母转换为小写。
lower
:把字符串转换为小写。
upper
:把字符串转换为大写。
title
:把字符串中的每个单词的首字母转换为大写。
trim
:去除字符串首尾的空白字符。
striptags
:删除字符串中所有 HTML 标签。
urlencode
:将字符串进行 URL 编码。
jsonify
:过滤器将变量内容转换为 JSON 格式的字符串。
first
:获取列表的第一个元素。
last
:获取列表的最后一个元素。
length
:获取字符串或列表的长度。
default
:如果一个变量未定义或为假(false),设置一个默认值。
示例:
{{ '<some_html>' | safe }}{{ 'JOHN DOE' | lower }}{{ [1, 2, 3, 4] | last }}
第五部分:使用 Jinja2 的高级特性
九. 宏、包含、测试、以及自定义过滤器等高级用法
1. 宏(Macros):
在 Jinja2 中,宏类似于 Python 的函数。你可以定义一块可重用的代码,并可以在模板中多次调用它。
{% macro render_comment(comment) %} <div class="comment"> <h2>{{ comment.author }}</h2> <p>{{ comment.content }}</p> </div>{% endmacro %}
你可以像这样在其他地方调用它:
{{ render_comment(comment) }}
2. 包含(Include):
include
语句允许你将一个模板中的内容包含进另一个模板。这有助于重用模板片段和组织代码。
<div> <h1>Welcome to my blog</h1> {% include 'includes/navigation.html' %}</div>
3. 测试(Tests):
Jinja2 中的测试用来检测变量的属性。例如,你可以检查一个变量是否是字符串、是否定义了等。
{% if comment is not none %} <p>Comment: {{ comment }}</p>{% endif %}
4. 自定义过滤器(Custom Filters):
Jinja2 允许你定义自己的过滤器。过滤器是当你需要执行变量转换时使用的函数。
要创建一个自定义过滤器,你需要先定义一个 Python 函数,然后通过app.template_filter()
注册为过滤器。
@app.template_filter('capitalize')def capitalize_filter(s): return s.capitalize()
在模板中使用这个过滤器:
<p>{{ "hello world" | capitalize }}</p>
这会输出 "Hello world"。
6. 综合示例:
from flask import Flask, render_templateapp = Flask(__name__)@app.template_filter('capitalize')def capitalize_filter(s): return s.capitalize()@app.route('/')def index(): comments = [ {'author': 'Alice', 'content': 'A great day!'}, {'author': 'Bob', 'content': 'Interesting post...'} ] return render_template('index.html', comments=comments)# 定义宏在模板文件中,例如 macros.html
macros.html
文件:
{% macro render_comment(comment) %} <div class="comment"> <h2>{{ comment.author | capitalize }}</h2> <p>{{ comment.content }}</p> </div>{% endmacro %}
index.html
文件:
{% from 'macros.html' import render_comment %}<html><body> {% include 'includes/navigation.html' %} <h1>Comments</h1> {% for comment in comments %} {{ render_comment(comment) }} {% endfor %}</body></html>
第六部分:表单与用户输入
介绍 Flask 中处理表单输入的方法。十. Flask 中处理表单输入的方法
在 Flask 中处理表单输入是通过 WTForms 或 Flask 自身的请求对象来进行的,这里将重点介绍如何使用 Flask 的 request 对象来处理表单输入。
1. Flask request 对象:
Flask 的 request
对象包含了来自客户端的所有请求数据。为了处理表单数据,你通常会从 request.form
属性中提取数据,它是一个类字典对象,包含了表单的键值对:
from flask import Flask, request, render_templateapp = Flask(__name__)@app.route('/form', methods=['GET', 'POST'])def form(): if request.method == 'POST': # 提取表单数据 username = request.form.get('username') email = request.form.get('email') password = request.form.get('password') # 处理表单数据 # ...(例如验证、存储至数据库等) # 返回响应或重定向 return 'Form Submitted!' # 如果请求方法是 GET,展示表单页面 return render_template('form.html')
在 form.html
模板中,你需要创建一个 HTML 表单指向 /form
路由并以 POST
方法提交,例子如下:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Form Example</title></head><body> <form action="/form" method="post"> <label for="username">Username:</label> <input type="text" id="username" name="username"> <label for="email">Email:</label> <input type="email" id="email" name="email"> <label for="password">Password:</label> <input type="password" id="password" name="password"> <input type="submit" value="Submit"> </form></body></html>
在上述示例中:
使用 @app.route
装饰器将函数 form()
绑定到路由 /form
上,允许 GET
和 POST
两种 HTTP 方法。
若 HTTP 请求为 POST
(表单提交后),从 request.form
中提取表单数据。
使用 request.form.get('input_name')
方法,安全地获取表单输入值,如果输入框未填写,则返回 None
。
在 Flask 中处理表单输入通常涉及以下步骤:
创建一个 HTML 表单用于接收用户输入。
在 Flask 应用中定义一个视图函数来处理表单提交的路由。
使用 Flask 的 request
对象处理提交的表单数据。
下面是一个简单的 Flask 脚本,展示了如何通过 POST 请求处理表单数据,并在提交后向用户反馈信息:
import flaskfrom flask import Flask, render_template, requestapp = Flask(__name__)@app.route('/submit', methods=['GET', 'POST'])def submit(): if request.method == 'POST': # 假设提交的表单有“name”和“age”字段 name = request.form['name'] age = request.form['age'] # 处理表单数据(如保存到数据库等) # 在实际应用中,你还需要进行数据的验证和清洗 return '表单提交成功!你的名字是 {} 年龄是 {}'.format(name, age) else: # 在 GET 请求下,渲染一个空的表单页面 return render_template('submit_form.html')if __name__ == '__main__': app.run(debug=True)
在该例子中,我们首先为路由 /submit
定义了一个视图函数 submit
。然后,根据 HTTP 请求的方法(GET 或 POST),执行不同的操作:
如果请求是 POST(这意味着用户提交了表单),我们从 request.form
字典中提取出用户通过表单输入的 name
和 age
字段,并返回一条确认信息。
如果请求是 GET(用户通过浏览器访问该页面),那么我们渲染并返回一个 HTML 表单,允许用户输入数据。
对应的 HTML 表单模板 submit_form.html
可能是这样的:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Submit Form</title></head><body> <form action="/submit" method="post"> <label for="name">姓名:</label> <input type="text" id="name" name="name"> <label for="age">年龄:</label> <input type="text" id="age" name="age"> <input type="submit" value="提交"> </form></body></html>
在这个表单中,我们有两个输入框和一个提交按钮。提交按钮会将表单数据以 POST 请求的方式发送到 /submit
路由。然后 Flask 应用中的 submit
视图函数会处理这些输入数据。
除了使用 request.form.get('input_name')
方法获取表单输入值,还有以下方式可用:
2. 使用索引直接访问:
这是获取表单输入值的最直接方式。你可以像访问字典一样,通过索引直接获取对应的值:
name = request.form['name']
请注意,如果表单中没有 'name' 字段,这种方式会引发一个 KeyError
。因此,除非你确定 'name' 字段一定存在,否则使用这种方式获取表单输入值可能并不安全。
3. 使用 request.form.getlist 方法:
如果你的 HTML 表单包含有多个具有相同名字的输入框(例如复选框组),那么你可能需要使用 request.form.getlist('input_name')
方法来获取所有选中的值:
selected_options = request.form.getlist('options')
此时 selected_options
会是一个列表,包含所有选中选项的值。
十一. WTForms 和如何简化表单处理
WTForms 是一个方便我们处理 Flask 网页表单的 Python 库。通过 WTForms,我们可以轻松定义表单类和验证规则,自动处理请求中表单字段的绑定,提升代码的效率和可读性。
1. 安装WTForms:
pip install wtforms
2. 在 Flask 中使用 WTForms:
2.1 定义表单类和字段
WTForms 让我们可以用类的形式定义表单,每个类的字段都可以是一个表单字段。举例来说,如果我们要创建一个包含 email
和 password
的登录表单,可以这样编写:
from flask_wtf import FlaskFormfrom wtforms import StringField, PasswordFieldfrom wtforms.validators import DataRequired, Emailclass LoginForm(FlaskForm): email = StringField('Email', validators=[DataRequired(), Email()]) password = PasswordField('Password', validators=[DataRequired()])
这里,LoginForm
类就表示一个表单,email
和 password
字段分别代表两个表单输入框。我们还添加了 DataRequired
和 Email
验证器,要求这两个字段不能为空,且 email
字段的值必须符合电子邮件格式。
2.2 在视图函数中使用表单
在视图函数中,我们可以生成表单实例并将其传递给模板。模板可以使用这个表单实例生成 HTML 表单:
from flask import render_template, requestfrom .forms import LoginForm@app.route('/login', methods=['GET', 'POST'])def login(): form = LoginForm() if form.validate_on_submit(): email = form.email.data password = form.password.data # 这里可以添加处理表单数据的代码(如检查用户身份) return 'Logged in successfully.' return render_template('login.html', form=form)
这里,form.validate_on_submit()
方法会在表单提交时进行字段验证,如果验证全部通过,方法会返回 True
。
2.3 在模板中渲染表单
在模板中,我们可以很方便地渲染出表单的 HTML 代码:
<form method="POST"> {{ form.hidden_tag() }} <p> {{ form.email.label }}<br> {{ form.email(size=20) }}<br> {% for error in form.email.errors %} <span style="color: red;">[{{ error }}]</span> {% endfor %} </p> <p> {{ form.password.label }}<br> {{ form.password(size=20) }}<br> {% for error in form.password.errors %} <span style="color: red;">[{{ error }}]</span> {% endfor %} </p> <p><input type="submit"