蓝图配置
蓝图是可用于在应用程序内进行子路由的对象。蓝图定义了添加路由的相似方法,而不是将路由添加到应用程序实例,然后以灵活且可插入的方式向应用程序注册。 蓝图对于大型应用程序特别有用,在大型应用程序中,您的应用程序逻辑可以分为几个组或职责范围。
我的第一个蓝图
下面显示了一个非常简单的蓝图,该蓝图在应用程序的根目录/中注册了处理程序功能。 假设您将此文件另存为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'})
注册蓝图
蓝图必须在应用程序中注册。
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='/')]
蓝图组和嵌套
蓝图也可以作为列表或元组的一部分进行注册,其中注册服务商将递归循环遍历任何蓝图的子序列,并进行相应的注册。所述Blueprint.group提供方法来简化这个过程,允许模拟什么从前端观察的“模拟”后端目录结构。考虑以下(非常人为的)示例:
api /
├──内容/
│├──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)
使用蓝图
蓝图具有与应用程序实例几乎相同的功能。
WebSocket路由
可以使用@ bp.websocket 装饰器或bp.add_websocket_route方法在蓝图上注册WebSocket处理程序。
蓝图中间件
使用蓝图,还可以全局注册中间件。
@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')
蓝图组中间件
使用此中间件将确保您可以将公共中间件应用于构成当前正在考虑的蓝图组的所有蓝图。
bp1 = Blueprint('bp1', url_prefix='/bp1')
bp2 = Blueprint('bp2', url_prefix='/bp2')
@bp1.middleware('request')
async def bp1_only_middleware(request):
print('applied on Blueprint : bp1 Only')
@bp1.route('/')
async def bp1_route(request):
return text('bp1')
@bp2.route('/<param>')
async def bp2_route(request, param):
return text(param)
group = Blueprint.group(bp1, bp2)
@group.middleware('request')
async def group_middleware(request):
print('common middleware applied for both bp1 and bp2')
# Register Blueprint group under the app
app.blueprint(group)
异常
例外可以专门应用于全局蓝图。
@bp.exception(NotFound)
def ignore_404s(request, exception):
return text("Yep, I totally found the page: {}".format(request.url))
静态文件 可以在蓝图前缀下全局提供静态文件。
# 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'
启动和停止
蓝图可以在服务器的启动和停止过程中运行功能。如果以多处理器模式运行(超过1个工作程序),则在工作程序派生后触发这些操作。
可用的事件有:
before_server_start:在服务器开始接受连接之前执行
after_server_start:在服务器开始接受连接后执行
before_server_stop:在服务器停止接受连接之前执行
after_server_stop:在服务器停止并且所有请求完成之后执行
bp = Blueprint('my_blueprint')
@bp.listener('before_server_start')
async def setup_connection(app, loop):
global database
database = mysql.connect(host='127.0.0.1'...)
@bp.listener('after_server_stop')
async def close_connection(app, loop):
await database.close()
用例:API版本控制
蓝图对于API版本控制非常有用,其中一个蓝图可能指向/ v1 /
初始化蓝图时,它可以使用可选的version参数,该参数将放在蓝图中定义的所有路由之前。此功能可用于实现我们的API版本控制方案。
# 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')
当我们在应用程序上注册蓝图时,路由/ v1 / api和/ v2 / api现在将指向各个蓝图,从而可以 为每个API版本创建子站点。
# 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)
URL建设与url_for
如果要为蓝图内部的路由生成URL,请记住端点名称采用
@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))