7. 蓝图
你的鼓励是我前进的动力,请为我点个赞吧!
蓝图对象可以对每一个子应用提供一个子路由。蓝图使用可插拔的方法为应用注册路由,而不是使用应用实例进行添加路由的方法。
蓝图一般用于大型的项目,尤其是该项目可以分解成几个不同的功能模块时。
(1) 蓝图的初步使用
接下来我们注册一个简单的注册函数用于处理根路由“/”的逻辑。建议开发者测试时使用my_blueprint.py保存文件,稍后将导入你的主模块中。
from sanic.response import json
from sanic import Blueprint
bp = Blueprint('my_blueprint')
@bp.route('/')
async def bp_root(request):
return json({'my': 'blueprint'})
(2)注册蓝图
蓝图的注册必须的使用应用app注册。
from sanic import Sanic
from my_blueprint import bp
app = Sanic(__name__)
app.blueprint(bp)
app.run(host='0.0.0.0', port=8000, debug=True)
这样将会将蓝图添加到应用中,并且将通过蓝图注册任意路由,通过使用app.router将会查看如下内容。
[Route(handler=<function bp_root at 0x7f908382f9d8>, methods=frozenset({'GET'}), pattern=re.compile('^/$'), parameters=[], name='my_blueprint.bp_root', uri='/')]
(3)蓝图分组与嵌套
蓝图可以注册列表或者元组的子序列,注册函数将会循环遍历的进行注册。Blueprint.group可以提供了模拟后台目录结构方法进行这样的处理。具体如下所示:
api/
├──content/
│ ├──authors.py
│ ├──static.py
│ └──__init__.py
├──info.py
└──__init__.py
app.py
初始化目录结果如图下所示:
# api/content/authors.py
from sanic import Blueprint
authors = Blueprint('content_authors', url_prefix='/authors')
# api/content/static.py
from sanic import Blueprint
static = Blueprint('content_static', url_prefix='/static')
# api/content/__init__.py
from sanic import Blueprint
from .static import static
from .authors import authors
content = Blueprint.group(static, authors, url_prefix='/content')
# api/info.py
from sanic import Blueprint
info = Blueprint('info', url_prefix='/info')
# api/__init__.py
from sanic import Blueprint
from .content import content
from .info import info
api = Blueprint.group(content, info, url_prefix='/api')
在app.py注册蓝图可以如下所示:
# app.py
from sanic import Sanic
from .api import api
app = Sanic(__name__)
app.blueprint(api)
(4)蓝图的使用
蓝图同应用一样具有相同的应用函数。
a.Websocket的路由
websocket处理函数可以通过@bp.websocket装饰器进行注册,或者使用bp.add_websocket_route进行注册。
b.中间件
使用蓝图可以注册全局中间件。
@bp.middleware
async def print_on_request(request):
print("I am a spy")
@bp.middleware('request')
async def halt_request(request):
return text('I halted the request')
@bp.middleware('response')
async def halt_response(request, response):
return text('I halted the response')
c.异常
@bp.exception(NotFound)
def ignore_404s(request, exception):
return text("Yep, I totally found the page: {}".format(request.url))
d.静态文件
静态文件为全局使用,要配置前缀。
suppose bp.name == 'bp'
bp.static('/web/path', '/folder/to/serve')
# also you can pass name parameter to it for url_for
bp.static('/web/path', '/folder/to/server', name='uploads')
app.url_for('static', name='bp.uploads', filename='file.txt') == '/bp/web/path/file.txt'
(5)开始与停止
蓝图可以在服务器开始和停止之间运行函数,如果运行在多处理器函系统中,这些函数将在worker fork之后触发。
可能发生的事件为:
* before_server_start:服务器链接之前执行
* after_server_start:服务器链接之后执行
* before_server_stop:服务器停止链接之前执行
* after_server_stop:服务器停止链接并完成所有链接之后执行
(6)AIP的版本控制
蓝图可以用于api的版本控制,一个接口可以指向/v1/,另一个接口指向/v2/。
蓝图初始化时可以配置一个version参数所有路由的版本控制。此属性可以用于版本控制策略。
# blueprints.py
from sanic.response import text
from sanic import Blueprint
blueprint_v1 = Blueprint('v1', url_prefix='/api', version="v1")
blueprint_v2 = Blueprint('v2', url_prefix='/api', version="v2")
@blueprint_v1.route('/')
async def api_v1_root(request):
return text('Welcome to version 1 of our documentation')
@blueprint_v2.route('/')
async def api_v2_root(request):
return text('Welcome to version 2 of our documentation')
当使用蓝图进行注册时,路由会指向不同处理函数。
# main.py
from sanic import Sanic
from blueprints import blueprint_v1, blueprint_v2
app = Sanic(__name__)
app.blueprint(blueprint_v1)
app.blueprint(blueprint_v2)
app.run(host='0.0.0.0', port=8000, debug=True)
(7)使用url_for构建url
假如开发者想要在蓝图内生成url,那么就要使用蓝图的名字和格式.<handler_name>
@blueprint_v1.route('/')
async def root(request):
url = request.app.url_for('v1.post_handler', post_id=5) # --> '/v1/api/post/5'
return redirect(url)
@blueprint_v1.route('/post/<post_id>')
async def post_handler(request, post_id):
return text('Post {} in Blueprint V1'.format(post_id))