Sanic官翻-蓝图

蓝图

蓝图是可用于在应用程序内进行子路由的对象。蓝图定义了添加路由的类似方法,不是向应用程序实例添加路由,而是以灵活且可插入的方式向应用程序注册。

蓝图对于大型应用程序特别有用,在大型应用程序中,您的应用程序逻辑可以分为几个组或职责范围。

简单示例

下面显示了一个非常简单的蓝图,该蓝图在应用程序的根目录/中注册了处理程序功能。

假设您将此文件另存为my_blueprint.py,以后可以将其导入到主应用程序中。

# 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/
├──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)

使用蓝图

蓝图具有与应用程序实例几乎相同的功能。

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_forbp.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/<routes>,而另一个蓝图则指向/v2/<routes>

初始化蓝图时,它可以使用可选的version参数,该参数将放在蓝图中定义的所有路由之前。此功能可用于实现我们的API版本控制方案

# blueprints.pyfrom sanic.response import textfrom sanic import Blueprintblueprint_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.pyfrom sanic import Sanicfrom blueprints import blueprint_v1, blueprint_v2app = Sanic(__name__)app.blueprint(blueprint_v1)app.blueprint(blueprint_v2)app.run(host='0.0.0.0', port=8000, debug=True)

使用url_for构建URL

如果要为蓝图内部的路由生成URL,请记住端点名称的格式为<blueprint_name>.<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))
原文地址:https://www.cnblogs.com/fhkankan/p/14763520.html