1 Flask概念
1.1 介绍
01.常用信息
a.应用对象
Flask应用对象是Flask程序的核心。你可以通过创建一个Flask类的实例来定义一个Flask应用对象。通常我们会将它命名为app。
b.路由
路由是Flask的核心概念之一。它定义了URL和处理请求的视图函数之间的映射。使用装饰器@app.route可以轻松地将URL路径与视图函数关联。
c.视图函数
视图函数是处理特定URL请求的Python函数。它们通常会返回一个响应对象,包含HTML、JSON或其他内容。
d.请求对象
Flask提供了一个全局对象request,包含了客户端请求的所有信息,例如数据、头信息、文件等。它是由Werkzeug库提供的。
e.响应对象
视图函数的返回值最终会被转化为一个响应对象。Flask提供了简便的方法来创建和操作这些响应对象。
f.模板
Flask使用Jinja2作为其模板引擎。模板允许将动态数据插入到HTML中。你可以在模板中使用控制结构(如循环和条件语句)来生成动态内容。
g.静态文件
Flask应用可以通过一个名为static的特殊文件夹来服务静态文件(如CSS、JavaScript、图片等)。这些文件可以通过/static/ URL访问。
h.配置
Flask应用可以通过配置对象或配置文件进行配置。这些配置项可以控制应用的行为,例如调试模式、数据库连接等。
i.扩展
Flask的设计使其非常容易扩展。有许多现成的Flask扩展可以集成到你的应用中,如Flask-SQLAlchemy(ORM)、Flask-Migrate(数据库迁移)、Flask-WTF(表单处理)等。
j.中间件
中间件是位于请求和响应之间的组件,可以用来处理或修改请求和响应。Werkzeug提供了中间件支持,Flask可以通过Werkzeug中间件进行扩展。
k.上下文
Flask有两个主要的上下文:应用上下文和请求上下文。应用上下文包含应用相关的数据,如配置和扩展实例。请求上下文包含与当前请求相关的数据,如请求对象和用户会话。
l.会话
Flask提供了会话机制来在多个请求之间存储用户数据。默认情况下,Flask会话是使用签名cookie实现的。
1.2 扩展
01.常用信息
a.Flask-SQLAlchemy
a.功能
提供SQLAlchemy ORM(对象关系映射)的集成,使数据库操作更加简单和Pythonic。
b.用途
简化数据库查询和操作,支持多种数据库后端。
b.Flask-Migrate
a.功能
基于Alembic,提供数据库迁移功能,便于管理数据库模式的变化。
b.用途
管理数据库版本,支持数据库模式的升级和降级。
c.Flask-WTF
a.功能
集成WTForms库,提供表单处理、表单验证和CSRF保护功能。
b.用途
简化表单创建和验证,增强应用的安全性。
d.Flask-Login
a.功能
提供用户会话管理功能,包括登录、登出和用户会话持久化。
b.用途
管理用户认证状态,支持用户登录和登出功能。
e.Flask-Mail
a.功能
用于发送电子邮件,支持各种电子邮件服务和协议。
b.用途
实现邮件通知、用户注册验证等功能。
f.Flask-RESTful
a.功能
简化创建REST API的过程,提供了用于定义API资源的类和方法。
b.用途
快速构建RESTful API,支持资源路由和请求处理。
g.Flask-Security
a.功能
提供一套完整的用户认证和授权功能,包括密码重置、注册、角色管理等。
b.用途
增强应用的安全性,支持用户权限管理。
h.Flask-Bootstrap
a.功能
集成Twitter Bootstrap框架,方便在Flask应用中使用Bootstrap的CSS和JavaScript组件。
b.用途
快速构建响应式Web界面,提升用户体验。
i.Flask-Caching
a.功能
提供缓存支持,支持多种缓存后端(如内存、Redis、Memcached等)。
b.用途
提高应用性能,减少数据库查询次数。
j.Flask-SocketIO
a.功能
基于Socket.IO,提供WebSocket支持,使实时通信变得简单。
b.用途
实现实时聊天、通知推送等功能。
k.Flask-Babel
a.功能
提供国际化和本地化支持,方便处理多语言应用。
b.用途
支持多语言翻译和日期格式化。
l.Flask-Admin
a.功能
提供一个可定制的管理后台界面,可以快速搭建管理后台。
b.用途
管理应用数据和用户,支持CRUD操作。
m.Flask-Celery
a.功能
集成Celery任务队列,支持异步任务处理和分布式任务队列。
b.用途
执行异步任务,支持任务调度和并行处理。
n.Flask-Uploads
a.功能
简化文件上传和管理,支持多种文件存储后端。
b.用途
处理用户上传的文件,支持文件验证和存储。
o.Flask-Testing
a.功能
提供单元测试支持,方便对Flask应用进行测试。
b.用途
编写和运行测试用例,确保应用功能的正确性。
p.Flask-Script(已过时,推荐使用Flask内置的flask命令)
a.功能
提供命令行解析功能,便于管理脚本任务。
b.用途
执行自定义管理命令,支持任务自动化。
q.Flask-Limiter
a.功能
提供速率限制功能,防止滥用API。
b.用途
控制API请求频率,保护服务器资源。
r.Flask-Principal
a.功能
提供权限管理和角色管理功能,便于实现复杂的权限控制。
b.用途
管理用户角色和权限,支持细粒度的访问控制。
s.Flask-CORS
a.功能
提供跨域资源共享(CORS)支持,允许跨域请求。
b.用途
解决跨域请求问题,支持前后端分离开发。
t.Flask-Cache(已被Flask-Caching取代)
a.功能
提供缓存机制,可以缓存视图函数的输出,减少服务器负载。
b.用途
提高应用性能,减少重复计算和数据库查询。
1.3 中间件
01.Werkzeug Middleware
a.ProxyFix
功能:处理代理服务器设置的中间件,确保正确获取客户端IP地址和协议。
用途:在应用部署在代理服务器后面时,确保应用能够正确识别客户端的真实IP地址和使用的协议(HTTP/HTTPS)。
b.SharedDataMiddleware
功能:提供静态文件服务的中间件,可以将请求路径映射到文件系统中的静态文件。
用途:用于开发环境中快速提供静态文件服务。
c.DispatcherMiddleware
功能:将不同的URL路径分派给不同的WSGI应用,是创建复合应用的好工具。
用途:在一个服务器实例中运行多个WSGI应用。
02.Flask扩展中间件
a.Flask-CORS
功能:处理跨域资源共享(CORS)的中间件,允许跨域请求。
用途:对于前后端分离的项目非常有用,解决跨域请求问题。
b.Flask-Limiter
功能:提供速率限制功能的中间件,用于防止API滥用。
用途:可以根据IP地址、用户等进行限流,保护API资源。
c.Flask-SSLify(已不再维护,推荐使用Flask-Talisman)
功能:强制使用HTTPS协议的中间件,重定向所有HTTP请求到HTTPS。
用途:确保应用通过HTTPS安全传输。
d.Flask-Talisman
功能:提供安全相关的HTTP头(如HSTS、CSP等)的中间件,增强Web应用的安全性。
用途:提高应用的安全性,防止常见的Web攻击。
e.Flask-Session
功能:扩展Flask会话机制的中间件,支持服务器端会话存储(如Redis、Memcached等)。
用途:提供更安全和持久的会话管理。
f.Flask-Compress
功能:为响应内容提供Gzip压缩的中间件,减少传输数据量,提高应用性能。
用途:优化网络传输,提高加载速度。
g.Flask-HTTPAuth
功能:提供HTTP基础认证和摘要认证的中间件,简化API认证流程。
用途:用于保护API,确保只有授权用户可以访问。
h.Flask-DebugToolbar
功能:提供调试信息的中间件,在开发环境中非常有用,可以显示详细的调试信息、SQL查询等。
用途:帮助开发者快速定位和解决问题。
i.Flask-Security
功能:集成多种安全功能的中间件,包括认证、授权、角色管理等。
用途:提供全面的安全解决方案,保护应用和用户数据。
j.Flask-Cache(已被Flask-Caching取代)
功能:提供缓存支持的中间件,可以缓存视图函数的输出,减少服务器负载。
用途:提高应用性能,减少重复计算。
k.Flask-Caching
功能:现代的缓存中间件,支持多种缓存后端,可以缓存视图和其他数据。
用途:优化性能,减少数据库查询和计算。
1.4 配置类
01.使用配置类
a.代码1
import logging
from datetime import timedelta
from urllib.parse import quote_plus as urlquote
class BaseConfig:
SUPERADMIN = 'admin'
SYSTEM_NAME = 'Pear Admin'
# 主题面板的链接列表配置
SYSTEM_PANEL_LINKS = [
{
"icon": "layui-icon layui-icon-auz",
"title": "官方网站",
"href": "http://www.pearadmin.com"
},
{
"icon": "layui-icon layui-icon-auz",
"title": "开发文档",
"href": "http://www.pearadmin.com"
},
{
"icon": "layui-icon layui-icon-auz",
"title": "开源地址",
"href": "https://gitee.com/Jmysy/Pear-Admin-Layui"
}
]
UPLOADED_PHOTOS_DEST = 'static/upload'
UPLOADED_FILES_ALLOW = ['gif', 'jpg']
UPLOADS_AUTOSERVE = True
# JSON配置
JSON_AS_ASCII = False
SECRET_KEY = "pear-system-flask"
# mysql 配置
MYSQL_USERNAME = "root"
MYSQL_PASSWORD = "123456"
MYSQL_HOST = "127.0.0.1"
MYSQL_PORT = 3306
MYSQL_DATABASE = "pradmin"
# 数据库的配置信息
# SQLALCHEMY_DATABASE_URI = 'sqlite:///../pear.db'
SQLALCHEMY_DATABASE_URI = f"mysql+pymysql://{MYSQL_USERNAME}:{urlquote(MYSQL_PASSWORD)}@{MYSQL_HOST}:{MYSQL_PORT}/{MYSQL_DATABASE}?charset=utf8mb4"
# 默认日志等级
LOG_LEVEL = logging.WARN
"""
flask-mail配置
"""
MAIL_SERVER = 'smtp.qq.com'
MAIL_USE_TLS = False
MAIL_USE_SSL = True
MAIL_PORT = 465
MAIL_USERNAME = '123@qq.com'
MAIL_PASSWORD = 'XXXXX' # 生成的授权码
MAIL_DEFAULT_SENDER = MAIL_USERNAME
# 插件配置,填写插件的文件名名称,默认不启用插件。
PLUGIN_ENABLE_FOLDERS = []
# 配置多个数据库连接的连接串写法示例
# HOSTNAME: 指数据库的IP地址、USERNAME:指数据库登录的用户名、PASSWORD:指数据库登录密码、PORT:指数据库开放的端口、DATABASE:指需要连接的数据库名称
# MSSQL: f"mssql+pymssql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=cp936"
# MySQL: f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4"
# Oracle: f"oracle+cx_oracle://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}"
# SQLite "sqlite:/// database.db"
# Postgres f"postgresql+psycopg2://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}"
# Oracle的第二种连接方式
# dsnStr = cx_Oracle.makedsn({HOSTNAME}, 1521, service_name='orcl')
# connect_str = "oracle://%s:%s@%s" % ('{USERNAME}', ' {PASSWORD}', dsnStr)
# 在SQLALCHEMY_BINDS 中设置:'{数据库连接别名}': '{连接串}'
# 最后在models的数据模型class中,在__tablename__前设置 __bind_key__ = '{数据库连接别名}' 即可,表示该数据模型不使用默认的数据库连接,改用“SQLALCHEMY_BINDS”中设置的其他数据库连接
# SQLALCHEMY_BINDS = {
# 'testMySQL': 'mysql+pymysql://test:123456@192.168.1.1:3306/test?charset=utf8',
# 'testMsSQL': 'mssql+pymssql://test:123456@192.168.1.1:1433/test?charset=cp936',
# 'testOracle': 'oracle+cx_oracle://test:123456@192.168.1.1:1521/test',
# 'testSQLite': 'sqlite:///database.db
# }
"""
session
"""
PERMANENT_SESSION_LIFETIME = timedelta(days=7)
SESSION_TYPE = "filesystem" # 默认使用文件系统来保存会话
SESSION_PERMANENT = False # 会话是否持久化
SESSION_USE_SIGNER = True # 是否对发送到浏览器上 session 的 cookie 值进行加密
b.代码2
import os
from flask import Flask
from applications.common.script import init_script
from applications.config import BaseConfig
from applications.extensions import init_plugs
from applications.view import init_bps
def create_app():
app = Flask(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
# 引入配置
app.config.from_object(BaseConfig)
# 注册flask组件
init_plugs(app)
# 注册蓝图
init_bps(app)
# 注册命令
init_script(app)
return app
1.5 路由、视图
01.常见信息1
a.路由(Routing)
路由是将URL与特定的视图函数关联起来的机制。它定义了客户端请求的URL路径与处理请求的视图函数之间的映射关系。
定义路由: 使用@app.route('/path')装饰器来定义路由。
示例:
@app.route('/hello')
def hello():
return 'Hello, World!'
b.视图(View)
视图函数是实际处理客户端请求的函数。它接收请求,处理业务逻辑,并返回响应。每个视图函数都与一个或多个路由关联。
视图函数的返回值: 可以是字符串、HTML模板、JSON数据等。
示例:
@app.route('/user/<username>')
def show_user_profile(username):
return f'User {username}'
c.蓝图(Blueprint)
蓝图是组织Flask应用的组件,用于将应用的不同部分分离到独立的模块中。蓝图使得应用的路由和视图可以模块化,便于管理和复用。蓝图可以在应用工厂模式中使用,有助于创建大型应用。
-----------------------------------------------------------------------------------------------------
定义蓝图: 使用Blueprint类来定义蓝图。
示例:
from flask import Blueprint
auth = Blueprint('auth', __name__)
@auth.route('/login')
def login():
return 'Login Page'
-----------------------------------------------------------------------------------------------------
注册蓝图: 在主应用中注册蓝图。
from flask import Flask
from .auth import auth
app = Flask(__name__)
app.register_blueprint(auth, url_prefix='/auth')
d.红图(Application Factories)
红图并不是Flask的官方术语,但在社区中,有时会用“红图”来指代应用工厂模式。这种模式通过创建一个函数来构建和配置Flask应用实例,使得应用的配置和初始化更加灵活和可复用。
-----------------------------------------------------------------------------------------------------
应用工厂: 使用一个函数来创建和配置Flask应用实例。
示例:
def create_app():
app = Flask(__name__)
app.config.from_object('config.Config')
# 在这里注册蓝图
from .auth import auth
app.register_blueprint(auth, url_prefix='/auth')
return app
e.总结
路由与视图: 路由通过装饰器将URL路径与视图函数关联。每当客户端访问特定URL时,Flask会调用相应的视图函数来处理请求。
蓝图与路由、视图: 蓝图将一组相关的路由和视图组织在一起,使得应用的模块化和复用更加容易。在主应用中注册蓝图后,蓝图中的路由和视图将成为应用的一部分。
红图与蓝图: 应用工厂模式(红图)通过函数创建应用实例,并在其中注册蓝图,从而使得应用的配置和初始化更加灵活。这种模式特别适用于大型应用和测试环境。
2 Flask扩展
2.1 Flask-SQLAlchemy
01.模型,有2种定义方式
a.方式1
import datetime
from applications.extensions import db
class Role(db.Model):
__tablename__ = 'admin_role'
id = db.Column(db.Integer, primary_key=True, comment='角色ID')
name = db.Column(db.String(255), comment='角色名称')
code = db.Column(db.String(255), comment='角色标识')
enable = db.Column(db.Integer, comment='是否启用')
remark = db.Column(db.String(255), comment='备注')
details = db.Column(db.String(255), comment='详情')
sort = db.Column(db.Integer, comment='排序')
create_time = db.Column(db.DateTime, default=datetime.datetime.now, comment='创建时间')
update_time = db.Column(db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment='更新时间')
power = db.relationship('Power', secondary="admin_role_power", backref=db.backref('role'))
b.方式2
from applications.extensions import db
# 创建中间表
role_power = db.Table(
"admin_role_power", # 中间表名称
db.Column("id", db.Integer, primary_key=True, autoincrement=True, comment='标识'), # 主键
db.Column("power_id", db.Integer, db.ForeignKey("admin_power.id"), comment='用户编号'), # 属性 外键
db.Column("role_id", db.Integer, db.ForeignKey("admin_role.id"), comment='角色编号'), # 属性 外键
)
02.Schema,有2种定义方式
a.方式1
# 定义User模型,表示用户表
class User(db.Model):
__tablename__ = 'users' # 指定表名
id = db.Column(db.Integer, primary_key=True) # 主键
username = db.Column(db.String(80), unique=True,
nullable=False) # 用户名字段,唯一且不为空
email = db.Column(db.String(120), unique=True, nullable=False) # 邮箱字段,唯一且不为空
password = db.Column(db.String(128), nullable=False) # 密码字段,不为空
created_at = db.Column(db.DateTime,
default=db.func.current_timestamp()) # 创建时间,默认当前时间
updated_at = db.Column(db.DateTime, default=db.func.current_timestamp(),
onupdate=db.func.current_timestamp()) # 更新时间,默认当前时间,在更新时自动更新
# 定义一对多关系,用户可以有多篇文章
posts = db.relationship('Post', backref='author', lazy=True)
# 定义对象的官方字符串表示,便于调试和日志记录
def __repr__(self):
return f'<User {self.username}>'
b.方式2
# 定义Post模型,表示帖子表
class Post(db.Model):
__tablename__ = 'posts' # 指定表名
id = db.Column(db.Integer, primary_key=True) # 主键
title = db.Column(db.String(200), nullable=False) # 标题字段,不为空
content = db.Column(db.Text, nullable=False) # 内容字段,不为空
author_id = db.Column(db.Integer, db.ForeignKey('users.id'),
nullable=False) # 定义外键,引用users表的id字段
created_at = db.Column(db.DateTime,
default=db.func.current_timestamp()) # 创建时间,默认当前时间
updated_at = db.Column(db.DateTime, default=db.func.current_timestamp(),
onupdate=db.func.current_timestamp()) # 更新时间,默认当前时间,在更新时自动更新
# 定义对象的官方字符串表示,便于调试和日志记录
def __repr__(self):
return f'<Post {self.title}>'
2.2 Flask-Migrate
01.常用信息1
a.介绍
Flask-Migrate 中的这些步骤确实主要用于管理数据库的结构变更,包括创建新表、修改表结构等操作。具体来说:
init():初始化迁移环境,会在项目中创建一个migrations目录,用于存储迁移脚本和其他相关信息。
migrate():根据模型类的变化生成迁移脚本,这些脚本描述了如何从当前数据库状态迁移到下一个状态。
upgrade():执行数据库迁移,将生成的迁移脚本应用到数据库中,包括创建新表、修改表结构等操作。
这些步骤确实是针对数据库结构的变更,如果数据库中已经存在这些表,则会按照脚本中定义的操作进行更新或者修改。但是,这些步骤本身并不会添加任何数据到数据库中。
b.注意事项
如果需要在迁移过程中添加初始数据,像之前提到的那样,你需要在迁移脚本中自行编写代码来添加数据,使用 db.session.add() 和 db.session.commit() 方法将数据写入数据库。
因此,Flask-Migrate 主要负责管理数据库结构的变更,而对于数据的添加和初始化,需要额外编写代码来完成。
2.3 Flask-WTF
01.常用信息1
a.介绍
Flask-WTF 是一个 Flask 扩展,用于处理 Web 表单。
它基于 WTForms 库,简化了在 Flask 应用程序中创建和处理表单的过程。
b.主要特点和功能包括
表单类的定义: 可以通过继承 FlaskForm 类来定义表单,使用 WTForms 提供的各种字段和验证器,例如文本字段 (StringField)、整数字段 (IntegerField)、密码字段 (PasswordField) 等,以及各种验证器来验证用户输入。
CSRF 保护: 默认情况下,Flask-WTF 自动为表单添加 CSRF 保护,以防止跨站请求伪造攻击。
表单渲染: 可以很方便地在 Flask 应用中渲染和处理表单,通过模板引擎(如 Jinja2)将表单对象传递到模板中,以便在 HTML 页面中显示和处理用户输入。
表单验证: 提供了强大的数据验证功能,可以在表单提交前对用户输入进行验证,确保输入的数据符合预期的格式和规则。
文件上传: 支持处理文件上传,通过 FileField 字段可以处理文件的上传和保存。
集成性: 可以与 Flask 的其他扩展和功能无缝集成,例如 Flask-SQLAlchemy、Flask-Migrate 等,使得在复杂的应用中管理和处理表单变得更加简单和高效。
总体来说,Flask-WTF 提供了一个快速、安全且易于使用的方法来处理 Web 应用程序中的表单,是开发 Flask 网站时的重要工具之一。
02.常用信息2
a.示例
# 导入必要的模块
from flask import Flask, render_template, redirect, url_for
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
# 创建Flask应用程序
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_secret_key_here'
# 创建一个简单的表单类
class MyForm(FlaskForm):
name = StringField('Name', validators=[DataRequired()])
submit = SubmitField('Submit')
# 定义路由和视图函数
@app.route('/', methods=['GET', 'POST'])
def index():
form = MyForm()
if form.validate_on_submit():
name = form.name.data
return f'Hello, {name}! Form submitted successfully.'
return render_template('index.html', form=form)
# 主函数
if __name__ == '__main__':
app.run(debug=True)
b.说明
FlaskForm 是从Flask-WTF中导入的基类,用于创建表单。
StringField 和 SubmitField 是从 wtforms 中导入的字段类,用于分别创建文本输入字段和提交按钮。
DataRequired 是从 wtforms.validators 中导入的验证器,用于确保字段中有数据。
MyForm 类定义了一个表单,其中 name 是一个必填的文本输入字段,submit 是一个提交按钮。
index 视图函数处理根路由 / 的 GET 和 POST 请求。当表单通过验证提交时,会显示提交成功的消息。
app.run(debug=True) 启动应用程序,debug=True 启用调试模式。
2.4 Flask-Login
01.常用信息1
@login_required 装饰器用于限制只有登录用户才能访问的视图。
使用:定义一个用户模型,通常需要继承 UserMixin,并实现 get_id() 方法和其他必要的方法
登录:login_user(user, remember=remember)
登出:logout_user()
2.5 Flask-Mail
01.常用信息1
用于在 Flask 应用程序中发送电子邮件。它简化了通过 SMTP 协议发送邮件的过程,
支持常见的邮件功能和配置选项,如安全连接、认证、附件等。
2.6 Flask-RESTful
01.常用信息1
a.简化的路由定义
Flask-RESTful 提供了 Resource 类,使得定义 API 资源变得简单明了。
你可以将不同的资源(如用户、书籍、订单等)定义为继承自 Resource 的类,
并为其定义 HTTP 方法(如 GET、POST、PUT、DELETE 等)来处理请求。
b.自动化的输入和输出序列化
Flask-RESTful 提供了内置的序列化和反序列化功能,
可以方便地将请求数据转换为 Python 对象,并将 Python 对象转换为 JSON 格式的响应数据。
这简化了数据的处理过程,减少了重复的代码。
c.请求参数解析
Flask-RESTful 内置了请求参数解析器,可以轻松地从请求中获取参数,并进行验证和转换。
这使得处理各种类型的请求参数变得简单和可靠。
d.错误处理
Flask-RESTful 提供了统一的错误处理机制,可以自定义错误响应和处理逻辑。
这使得在 API 开发过程中能够更好地控制和处理各种异常情况。
e.插件扩展支持
Flask-RESTful 可以与 Flask 的众多扩展库无缝集成,
如 Flask-SQLAlchemy(用于数据库操作)、Flask-JWT(用于身份验证和授权)、Flask-Cache 等,
使得开发和扩展 API 功能更加灵活和强大。
f.RESTful 规范支持
Flask-RESTful 遵循 RESTful API 设计的最佳实践,
包括使用 HTTP 方法来表示资源的操作(GET 用于获取资源,POST 用于创建资源,
PUT 用于更新资源,DELETE 用于删除资源等),使得 API 设计更加符合标准和规范。
02.常用信息2
a.代码
from flask import Flask, jsonify
from flask_restful import Api, Resource
# 创建 Flask 应用程序
app = Flask(__name__)
api = Api(app)
# 创建一个简单的数据集
books = [
{'id': 1, 'title': 'Python Programming', 'author': 'Guido van Rossum'},
{'id': 2, 'title': 'Flask Essentials', 'author': 'Randall Degges'}
]
# 创建一个继承自 Resource 的类来定义资源
class BookList(Resource):
def get(self):
# 返回所有书籍
return jsonify(books)
class Book(Resource):
def get(self, book_id):
# 返回特定 ID 的书籍
book = next(filter(lambda x: x['id'] == book_id, books), None)
return jsonify(book)
# 添加资源到 API 中,并定义访问路径
api.add_resource(BookList, '/books')
api.add_resource(Book, '/book/<int:book_id>')
# 定义主函数用于运行应用程序
def main():
app.run(debug=True)
# 程序入口点,运行主函数
if __name__ == '__main__':
main()
2.7 Flask-JWT
01.常用信息1
a.简化的身份验证机制
Flask-JWT 提供了简单的接口,帮助开发者实现基于 JWT 的身份验证机制。
开发者可以通过少量的代码,轻松地将 JWT 整合到他们的 Flask 应用中。
b.无状态的认证
JWT 能够在请求和响应之间传递用户信息,因此不需要在服务器端存储用户的认证状态。
这样的无状态特性使得 JWT 非常适合用于分布式和跨域环境。
c.安全性
JWT 使用了基于加密的签名机制来保证数据的完整性和安全性。
通过设置密钥(Secret Key),可以有效地防止 JWT 被篡改或伪造。
d.灵活的自定义配置
开发者可以根据自己的需求,自定义 JWT 的过期时间、加密算法以及其他参数。
这种灵活性使得 JWT 可以适应各种不同的安全需求。
e.与 Flask 框架的无缝集成
Flask-JWT 与 Flask 框架天然集成,可以与 Flask 的路由和中间件无缝配合,
方便地实现对 API 端点的身份验证和访问控制。
02.常用信息2
a.示例
from flask import Flask, jsonify
from flask_jwt import JWT, jwt_required, current_identity
# 用户数据模型
class User(object):
def __init__(self, id, username, password):
self.id = id
self.username = username
self.password = password
# 用户列表
users = [
User(1, 'user1', 'password1'),
User(2, 'user2', 'password2')
]
# 根据用户名查找用户
def authenticate(username, password):
user = next(
filter(lambda u: u.username == username and u.password == password, users),
None)
if user:
return user
# 根据用户 ID 查找用户
def identity(payload):
user_id = payload['identity']
return next(filter(lambda u: u.id == user_id, users), None)
# 创建 Flask 应用程序
app = Flask(__name__)
app.config['SECRET_KEY'] = 'super-secret'
# 创建 JWT 对象
jwt = JWT(app, authenticate, identity)
# 受保护的资源,需要验证才能访问
@app.route('/protected', methods=['GET'])
@jwt_required()
def protected():
return jsonify(id=current_identity.id,
username=current_identity.username), 200
# 定义主函数用于运行应用程序
if __name__ == '__main__':
app.run(debug=True)
b.说明
导入必要的模块 Flask、Flask-JWT 和 werkzeug.security。
创建一个简单的 User 类来模拟用户数据,包含 id、username 和 password 属性。
创建一个用户列表 users,存储两个示例用户。
定义 authenticate 函数,用于验证用户名和密码是否匹配,返回用户对象。
定义 identity 函数,根据 JWT 负载中的用户 ID 查找并返回对应的用户对象。
创建 Flask 应用 app,设置 SECRET_KEY 以用于加密 JWT。
创建 JWT 对象 jwt,传入 app、authenticate 和 identity 函数,用于处理身份验证和授权。
定义受保护的路由 /protected,使用 @jwt_required() 装饰器标记,表示该资源需要进行 JWT 验证才能访问。
在 /protected 路由中,通过 current_identity 获取当前用户的信息,并返回用户的 id 和 username。
在程序入口处,通过 if __name__ == '__main__': 判断,如果直接运行此文件,则调用 app.run() 启动应用。
2.8 Flask-JWT-Extended
01.常用信息1
a.确保安装了 Flask 和 Flask-JWT-Extended 库。可以使用 pip 安装:
pip install Flask Flask-JWT-Extended
b.配置应用
在 Flask 应用中配置 JWT 扩展。例如:
from flask import Flask
from flask_jwt_extended import JWTManager
app = Flask(__name__)
# 设置秘钥,用于签名 JWT
app.config['JWT_SECRET_KEY'] = 'your-secret-key'
jwt = JWTManager(app)
c.定义认证逻辑
创建认证逻辑,例如登录视图函数,用于生成 JWT。
from flask import jsonify, request
from flask_jwt_extended import create_access_token, jwt_required, get_jwt_identity
@app.route('/login', methods=['POST'])
def login():
username = request.json.get('username', None)
password = request.json.get('password', None)
if username != 'user' or password != 'password':
return jsonify({"msg": "Bad username or password"}), 401
access_token = create_access_token(identity=username)
return jsonify(access_token=access_token), 200
d.保护资源
使用 jwt_required 装饰器来保护需要认证的资源。
@app.route('/protected', methods=['GET'])
@jwt_required()
def protected():
current_user = get_jwt_identity()
return jsonify(logged_in_as=current_user), 200
e.处理权限
如果需要更精细的权限控制,可以使用 @jwt_required 装饰器结合 get_jwt_claims 来检查用户的权限声明。
这个例子中,要求 JWT 的声明中包含一个 role 字段,并且其值为 admin 才能访问。
@app.route('/admin', methods=['GET'])
@jwt_required()
def admin():
current_user = get_jwt_identity()
claims = get_jwt_claims()
if claims['role'] != 'admin':
return jsonify(msg='Admins only!'), 403
return jsonify(admin_resource='secret'), 200
02.常用信息2
a.create_access_token(identity)
create_access_token 函数用于生成 JWT 访问令牌,基于提供的身份信息。
参数:identity:表示用户的标识信息,通常是用户名或用户 ID。
返回值:返回一个字符串,即生成的 JWT 访问令牌。
-----------------------------------------------------------------------------------------------------
from flask_jwt_extended import create_access_token
# 假设用户登录成功后,生成 JWT 访问令牌
username = 'user'
access_token = create_access_token(identity=username)
b.jwt_required()
jwt_required 是一个装饰器,用于保护需要 JWT 认证的路由,确保请求中包含有效的 JWT 访问令牌。
-----------------------------------------------------------------------------------------------------
from flask import jsonify
from flask_jwt_extended import jwt_required, get_jwt_identity
# 受保护的路由,需要 JWT 认证
@app.route('/protected', methods=['GET'])
@jwt_required()
def protected():
# 获取 JWT 中包含的身份信息
current_user = get_jwt_identity()
return jsonify(logged_in_as=current_user), 200
c.get_jwt_identity()
get_jwt_identity 函数用于从当前请求的 JWT 访问令牌中获取身份信息。
返回值:返回一个字符串,即 JWT 中包含的身份信息(例如用户名或用户 ID)。
-----------------------------------------------------------------------------------------------------
from flask import jsonify
from flask_jwt_extended import jwt_required, get_jwt_identity
# 受保护的路由,需要 JWT 认证
@app.route('/protected', methods=['GET'])
@jwt_required()
def protected():
# 获取 JWT 中包含的身份信息
current_user = get_jwt_identity()
return jsonify(logged_in_as=current_user), 200
d.总结
除了上述介绍的核心功能外,Flask-JWT-Extended 还提供了其他有用的功能和装饰器,例如:
get_raw_jwt():获取原始的 JWT 数据。
create_refresh_token(identity):生成 JWT 刷新令牌。
jwt_refresh_token_required():保护需要刷新令牌的路由。
get_jwt_claims():获取 JWT 中的声明信息。
jwt_optional():标记路由为可选 JWT 认证,即可以提供或不提供有效 JWT 访问令牌。
2.9 Flask-Security
01.常用信息1
a.代码
from flask import Flask
from flask_security import Security, SQLAlchemyUserDatastore, UserMixin, \
RoleMixin, login_required
from flask_sqlalchemy import SQLAlchemy
# 创建 Flask 应用
app = Flask(__name__)
app.config['SECRET_KEY'] = 'super-secret' # 应用的密钥
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///demo08.db' # SQLite 数据库 URI
app.config['SECURITY_PASSWORD_SALT'] = 'salt' # 密码盐值
# 创建 SQLAlchemy 实例
db = SQLAlchemy(app)
# 用户-角色关联表
roles_users = db.Table('roles_users',
db.Column('user_id', db.Integer(),
db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(),
db.ForeignKey('role.id'))
)
# 角色模型
class Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(80), unique=True)
# 用户模型
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(255), unique=True)
password = db.Column(db.String(255))
active = db.Column(db.Boolean())
roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'))
# Flask-Security 需要的用户数据存储对象
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
# 创建 Security 实例
security = Security(app, user_datastore)
# 创建数据库表结构
def create_db():
db.create_all()
# 保护的路由,需要登录才能访问
@app.route('/protected')
@login_required
def protected_route():
return 'This is a protected route!'
# 主函数,用于运行 Flask 应用
def main():
create_db() # 创建数据库表结构
app.run(debug=True)
if __name__ == '__main__':
main()
b.说明
导入了 Flask 相关模块和 Flask-Security 扩展。
创建了 Flask 应用 app,并配置了应用的 SECRET_KEY、数据库 URI 和密码盐值。
使用 SQLAlchemy 创建了数据库实例 db。
定义了角色模型 Role 和用户模型 User,并创建了用户-角色关联表 roles_users。
创建了 SQLAlchemyUserDatastore 对象 user_datastore,用于处理用户和角色的数据存储。
初始化了 Security 实例,并将 app 和 user_datastore 传递进去。
定义了保护的路由 /protected,使用 @login_required 装饰器确保只有登录用户才能访问。
编写了 create_db() 函数,用于创建数据库表结构。
在 main() 函数中调用 create_db() 函数创建数据库表,并通过 app.run() 启动 Flask 应用。
2.10 Flask-Uploads
01.常用信息1
a.代码
from flask import Flask, request, render_template
from flask_uploads import UploadSet, configure_uploads, IMAGES
app = Flask(__name__)
app.config['SECRET_KEY'] = 'super-secret' # 应用的密钥
# 配置文件上传目录和允许的文件类型
photos = UploadSet('photos', IMAGES)
app.config['UPLOADED_PHOTOS_DEST'] = 'uploads' # 文件上传目录
configure_uploads(app, photos) # 配置上传集合
# 文件上传路由和视图函数
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST' and 'photo' in request.files:
filename = photos.save(request.files['photo'])
return f'File {filename} uploaded successfully!'
return render_template('upload.html')
# 主函数,用于运行 Flask 应用
def main():
app.run(debug=True)
if __name__ == '__main__':
main()
b.说明
导入 Flask 相关模块和 Flask-Uploads 扩展。
创建 Flask 应用 app,设置应用的密钥和文件上传配置。配置了一个名为 photos 的上传集合,限制为图片类型 (IMAGES)。
定义了 /upload 路由,用于处理文件上传。在 POST 方法中,通过 photos.save() 方法保存上传的文件,并返回成功上传的消息。
创建了一个简单的 HTML 模板 upload.html,包含一个文件上传表单。
定义了 main() 函数用于运行 Flask 应用,通过 app.run() 启动应用。
2.11 Flask-Session
01.常用信息1
a.代码
from flask import Flask, session
from flask_session import Session
app = Flask(__name__)
app.config['SECRET_KEY'] = 'super-secret-key' # 设置应用的密钥
# 配置 Flask-Session
app.config['SESSION_TYPE'] = 'filesystem' # 选择会话存储方式为文件系统
Session(app)
# 定义一个简单的路由,用于设置和获取会话数据
@app.route('/set_session')
def set_session():
"""
设置会话数据。
"""
session['username'] = 'user@example.com'
return 'Session is set!'
@app.route('/get_session')
def get_session():
"""
获取会话数据。
"""
if 'username' in session:
return f'Logged in as {session["username"]}'
return 'Session not set'
# 主函数,用于运行 Flask 应用
def main():
"""
主函数,用于运行 Flask 应用。
"""
app.run(debug=True)
if __name__ == '__main__':
main()
b.说明
Flask:用于创建 Flask 应用。
session:用于访问会话对象,存储和获取会话数据。
redirect, url_for:用于重定向和 URL 构建。
Session:Flask-Session 扩展,用于管理 Flask 中的会话。
Flask(__name__):创建 Flask 应用对象。
app.config['SECRET_KEY']:设置应用的密钥,用于会话加密和安全性。
app.config['SESSION_TYPE']:设置会话存储方式为文件系统,可选的还有 'redis', 'mongodb', 'sqlalchemy' 等。
Session(app):初始化 Flask-Session 扩展,将会话配置应用到 Flask 中。
/set_session 路由:设置会话数据 session['username']。
/get_session 路由:获取并显示会话数据 session['username']。
2.12 Flask-CORS
01.常用信息1
a.代码
from flask import Flask, jsonify
from flask_cors import CORS
app = Flask(__name__)
app.config['SECRET_KEY'] = 'super-secret' # 设置应用的密钥
# 启用 CORS 支持,允许所有来源访问
CORS(app)
# 定义一个简单的路由,返回JSON数据
@app.route('/api/data', methods=['GET'])
def get_data():
data = {'message': 'Hello, CORS!'}
return jsonify(data)
# 主函数,用于运行 Flask 应用
def main():
"""
主函数,用于运行 Flask 应用。
"""
app.run(debug=True)
if __name__ == '__main__':
main()
b.说明
使用 CORS(app) 启用 CORS 支持,并允许所有来源访问。
可以根据需求进行更精细的配置,如设置具体的来源或允许的 HTTP 方法等。
3 FastAPI
3.1 处理参数
01.请求参数
a.路径参数 (Path Parameters)
a.定义
路径参数是 URL 路径的一部分。例如,/items/{item_id} 中的 item_id 就是一个路径参数。
b.使用方法
使用 Path 类来定义路径参数并可以添加描述。
from fastapi import Path
@app.get("/items/{item_id}")
async def read_item(item_id: int = Path(..., description="The unique ID of the item")):
return {"item_id": item_id}
c.注意事项
item_id: int 是强制类型申明,会强制类型转化,如果转化错误,会校验错误。
b.查询参数 (Query Parameters)
a.定义
查询参数出现在 URL 的 ? 后面,通常用于过滤、排序等。可以是可选的。
b.使用方法
from fastapi import Query
@app.get("/items/")
async def read_items(q: str = Query(None, description="Search query")):
return {"q": q}
c.请求体 (Request Body)
a.定义
请求体用于 POST、PUT 和 PATCH 请求,通常用来发送数据(如 JSON、XML 等)。
b.使用方法
使用 Pydantic 模型 来定义请求体的格式,并可以为字段添加描述。
from pydantic import BaseModel
from fastapi import Body
from typing import Union, Optional
class Item(BaseModel):
name: str
description: str
birth: Union[date, None] = None
desc: Optional[str] = None
@app.post("/items/")
async def create_item(item: Item = Body(..., description="The item to create")):
return {"name": item.name, "description": item.description}
c.注意事项
请求体常用于提交较大或复杂的数据。
d.表单参数 (Form Parameters)
a.定义
表单参数通常用于 POST 请求中的表单数据提交。
b.使用方法
from fastapi import Form
@app.post("/submit/")
async def submit_form(name: str = Form(...), age: int = Form(...)):
return {"name": name, "age": age}
e.文件上传 (File Uploads)
a.定义
FastAPI 支持文件上传,允许通过表单字段上传文件。
b.使用方法
from fastapi import File, UploadFile
@app.post("/upload/")
async def upload_file(file: UploadFile = File(...)):
return {"filename": file.filename}
f.Cookie 参数 (Cookie Parameters)
a.定义
如果你需要从请求的 cookies 中获取数据,可以使用 Cookie 类。
b.使用方法
from fastapi import Cookie
@app.get("/items/")
async def get_items(cookie_id: str = Cookie(None)):
return {"cookie_id": cookie_id}
g.头部参数 (Header Parameters)
a.定义
如果你需要从请求的头部获取数据,可以使用 Header 类。
b.使用方法
from fastapi import Header
@app.get("/items/")
async def get_items(user_agent: str = Header(None)):
return {"user_agent": user_agent}
h.Request参数 (Request参数 Parameters)
a.定义
如果你需要从Request参数获取数据,可以使用 Request 类。
b.使用方法
from fastapi import Request
@app.get("/items/")
async def get_items(request: Request):
return {"url": request.url}