使用扩展增强Flask功能
Flask自身仅包含非常核心的功能,其更加强大的功能是由扩展来提供的。以下选择几个常用的扩展进行介绍,更加丰富的扩展列表可以在Flask Extensions找到。
扩展一般都命名为Flask-ExtName
或者ExtName-Flask
的形式。要使用一个扩展,可以直接在主启动文件(Flask实例初始化的文件)中通过传入Flask实例来完成扩展的载入和实例化。例如:
from flask-foo import Foo
foo = Foo()
app = Flask(__name__)
foo.init_app(app)
常用的Flask扩展有以下这些,其具体用法可以参考其文档。
- Flask-SQLAlchemy:SQLAlchemy的Flask扩展,允许在Flask中便捷的使用SQLAlchemy。
- Flask-WTF:提供了WTForms的接入,允许以简便的方法处理表单。
- Flask-Peewee:提供Peewee ORM的接入。
- Flask-OAtuh:提供了OAuth的支持。
- Flask-Mail:提供了比较简单的发送邮件的支持。
- Flask-Mako:允许使用Mako模板引擎来替代Jinja2。
- Flask-Login:提供Flask对于用户Session的管理,支持用户的登入、登出以及会话记录等功能。
- Flask-HTTPAuth:提供了Flask对于HTTP Header认证的支持。
- Flask-Security:提供简单易用的安全与验证功能。
- Flask-SSE:提供了Server Send Events的支持。
- Flask-XML-RPC:提供了XML-RPC的支持。
- Flask-Celery:提供了Celery的接入。
- Flask-Bcrypt:提供了Bcrypt加密、散列功能支持。
- Flask-SocketIO:提供了WebSocket功能的支持。
- Flask-PageDown:提供了PageDown的包装,用于将Markdown转换为HTML。
- Flask-KVsession:使用服务器端存储实现的用户Session。
- Flask-Assets:用于合并、压缩、编译CSS和Javascript等静态资源文件。
- Falsk-ApScheduler:定时任务框架。
- Flask_nameko:用于在Flask中使用Nameko微服务。
Flask-SQLAlchemy
SQLAlchemy是Python中常用的ORM框架,Flask提供了一个扩展来允许用户更加便捷的在Flask应用中使用SQLAlchemy。Flask-SQLAlchemy主要提供了随着Flask实例启动数据库连接和关闭数据库连接的功能,其中数据表映射定义及查询等功能都没有任何变化,唯一的变化可能是不再需要引入sqlalchemy.orm
。
以下示例引入了Flask-SQLAlchemy,并将其载入了Flask实例。
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////temp/test.db'
db = SQLAlchemy(app)
从示例中可以看出,Flask-SQLAlchemy是通过app.config['SQLALCHEMY_DATABASE_URI']
来指定要连接的数据库内容的,所以可以在配置文件中将此配置项写入以便不在代码中进行硬编码。之后整个应用中的数据库操作均可以通过db
来完成,其中数据表映射定义要使用的Column()
等方法,均已包含在db
中,可以直接使用。
对于使用类来进行数据表映射,之前独立使用SQLAlchemy时需要先建立一个Base
基类,这项工作在Flask-SQLAlchemy中已经完成,可以直接继承db.Model
类即可。
Flask-SQLAlchemy常用的配置项有:
SQLALCHEMY_DATABASE_URI
,指定SQLAlchemy要连接的数据库URI,格式与SQLAlchemy中连接串格式相同。SQLALCHEMY_ECHO
,在SQL语句出现错误时,是否输出全部SQL语句。SQLALCHEMY_POOL_SIZE
,指定数据库连接池的大小。SQLALCHEMY_POOL_TIMEOUT
,指定数据库连接池中连接的超时时间,单位是秒。SQLALCHEMY_POOL_RECYCLE
,指定数据库连接池中连接的空闲回收时间,当空闲超过本时间后,连接即被关闭回收,单位是秒。SQLALCHEMY_MAX_OVERFLOW
,指定当数据库连接池连接数达到指定大小时,还可以创建的最大连接数。
对于数据表的查询可以直接使用实体来完成,增删改可以借助db.session
来完成,这部分操作与SQLAlchemy中的操作完全一致。
在Restful Web应用中,常常会以JSON格式输出数据内容,但是如果直接使用jsonify()
对SQLAlchemy查询结果进行序列化时,往往会得到XXX is not JSON serializable
的错误,这是因为SQLAlchemy返回的实体是一个复杂结构,并不能简单的转换为字典等简单数据类型。要完成SQLAlchemy实体向字典类型的转换,推荐采用marshmallow库,具体使用可参考相应章节的介绍。
Flask-SocketIO
Flask本身不带WebSocket的实现,如果要在Flask框架上使用WebSocket功能,需要使用Flask-SocketIO扩展来完成。在客户端可以使用socket.io库来完成功能对接。
Flask-SocketIO的初始化十分简单,而且与Flask-SQLAlchemy基本相似。
from flask import Flask
from flask_socketio import SokcetIO
app = Flask(__name__)
app.config['SECRET_KEY'] = b'key'
socketio = SocketIO(app)
Flask-SocketIO通过修饰器来设定相应WebSocket事件的处理函数。@socketio.on(param)
可以用来接收命名事件与未命名事件的信息。如果param
的值为'message'
则被修饰的处理函数可以接受未命名事件,并将其发送的内容作为参数收集起来;如果param
的值为'json'
,则可以使用JSON解析客户端发送的未命名事件。
如果在@socketio.on(param)
中传入一个自定义的事件名称,则处理函数就会响应带有自定义事件的请求。所有类型的处理函数都可以接受多个参数。此外,@socketio.on(param)
还可以接受一个额外的命名参数namespace
,指定不同的namespace
可以允许客户端与WebSocket之间建立多条独立连接。
WebSocket是双向通讯的,所以Flask-SocketIO也同样支持消息的发送。消息发送功能是通过Flask-SocketIO提供的send()
和emit()
两个函数完成的。其中send()
函数用来发送未命名事件,emit()
用来发送命名事件。两个函数的使用格式基本一致,其中emit()
的第一个参数为事件名称,第二个参数为消息内容,并且支持发送多个消息内容;而send()
函数由于是发送未命名事件,所以其参数直接为消息内容。两个参数都可以接一个名称为namespace
的参数,这可以允许两个函数将消息发送至指定的命名空间(连接)中。
在默认情况下,send()
和emit()
都是与客户端一对一进行消息收发操作的,如果服务器需要群发通知,则需要给这两个函数添加一个命名参数broadcast=True
,这就表示本次消息发送为广播发送,所有已连接的客户端都会收到消息。
下面给出Flask-SocketIO的一些常用修饰器及响应事件的标识。
@socketio.on(event, namespace='/')
,用于对客户端发送数据进行响应。'message'
,未命名事件,直接获取数据。'json'
,未命名事件,以JSON格式解析数据。'custom event'
,命名事件,可以接受任意类型数据。'connect'
,客户端连接事件。'disconnect'
,客户端断开事件。'join'
,客户端加入群事件。'leave'
,客户端离开群事件。
@socketio.on_error()
,用于响应默认命名空间内的错误,指定命名空间后响应指定命名空间的错误。@socketio.on_error_default
,用于响应所有命名空间内的错误。
其他更多的使用方式可参考Flask-SocketIO的文档。
Flask-Script
Flask-Script扩展向Flask提供了插入外部脚本的功能,常用功能主要有以下几个。
- 运行一个开发用的服务器。
- 运行一个定制的Python Shell。
- 设置数据库。
- 定时任务。
- 运行Web应用之外的命令。
在很多线上教程的示例中,都会出现一个专门用于管理Flask站点的manager.py
,并且一般通过这个文件来完成Flask运行实例的管理。这个文件可以通过Flask-Script来实现功能。
Manager类
Flask-Script提供了一个Manager
类,可以使用它来管理一个Flask实例。其最简单的使用示例如下。
from flask_script import Manager
from app import app
manager = Manager(app)
if __name__ == '__main__':
manager.run()
在这个最简单的示例中,只需要执行python manager.py
即可启动Manager实例并运行Flask应用实例。Manager
实例还可以接受命令行命令来完成额外的功能。在Flask-Script中,命令的定义有三种方式。
- 创建Command子类,实现其中的
run()
方法,并使用Manager
的add_command()
方法将其添加到Manager实例中。 - 使用
@manager.command
修饰器修饰一个函数,函数名即可成为一个命令。 - 使用
@manager.option()
修饰器修饰一个函数,函数名即可成为一个命令,并且可以接受参数。一个函数可以被多个@manager.option()
修饰器修饰。
以下给出一个详细的使用示例。
from flask_script import Manager
from app import create_app
manager = Manager(create_app)
@manager.option('-n', '--name', dest='name', help='App name', default='APP')
@manager.option('-p', '--port', dest='port', default=8080)
def start(name, port):
print(name)
print(port)
if __name__ == '__main__':
manager.run()
在这个示例中,dest='name'
指定了这个Option修饰器定义的参数对应的函数参数名称,并且可以在执行命令python manager.py start -n MyApp
时将参数传入函数进行处理。
Manager实例可以通过add_command()
方法嵌套使用,以形成一套复杂的命令行控制。
Server类
Server类是Flask-Script中提供的开发服务器。Server类一般会提供一个默认的命令和配置。以下给出一个常见的使用方法。
from flask_script import Server, Manager
from app import create_app
manager = Manager(create_app)
server = Server(host='0.0.0.0', port=9000)
manager.add_command('runserver', server)
if __name__ == '__main__':
manager.run()
当在命令行中执行python manager.py runserver
时,便会按照配置启动Flask应用。
Flask_Nameko
Flask_Nameko用于在Flask中对Nameko微服务进行包装。Flask_Nameko可以通过命令pip install flask_nameko
完成安装。
要使用Flask_Nameko,需要在Flask app中对Nameko进行初始化,Flask_Nameko提供了一个FlaskPooledClusterRpcProxy
类来与Nameko的RPC服务集群进行通信。初始化过程一般可以参考以下示例。
from flask import Flask
from flask_nameko import FlaskPooledClusterRpcProxy
rpc = FlaskPooledClusterRpcProxy()
def create_app():
app = Flask(__name__)
rpc.init_app(app)
app = create_app()
之后在需要调用RPC服务的位置就可以如以下示例中一般使用。
from . import app, rpc
@app.route('/')
def index():
result = rpc.service.some_method('some_value')
return result
FlaskPooledClusterRpcProxy可以接受所有Nameko中的配置项,但前面需要添加NAMEKO_
前缀。除Nameko定义的配置项以外,Flask_Nameko还定义了以下配置项供使用。
NAMEKO_INITIAL_CONNECTIONS
,初始创建的连接数量,默认为2。NAMEKO_MAX_CONNECTIONS
,最大创建的连接数量,默认为8。NAMEKO_CONNECT_ON_METHOD_CALL
,决定何时加载连接到服务的连接,False
表示在连接到服务时,True
表示调用RPC方法时。NAMEKO_RPC_TIMEOUT
,调用RPC方法的默认超时时间。NAMEKO_POOL_RECYCLE
,连接池连接回收的秒数,连接大于指定秒数的将被自动回收。