前后端知识库 前后端知识库
首页
    • JavaScript
    • React
    • Vue
  • Python
  • Sanic
  • Linux
  • Ansible
归档
GitHub (opens new window)
首页
    • JavaScript
    • React
    • Vue
  • Python
  • Sanic
  • Linux
  • Ansible
归档
GitHub (opens new window)
  • Sanic

    • 开始
    • Routing
    • 请求数据
    • 响应
    • 静态资源
    • 异常
    • 中间件 和 监听器
    • 蓝图
      • 我的第一个蓝图
      • 注册蓝图
      • 蓝图 组 和 嵌套
      • 使用蓝图
        • WebSocket 路由
        • 中间件
        • 异常
        • 静态文件
      • 启动和停止
      • 用例: API 版本
      • 用 url_for 建立 URL
    • WebSocket
    • 配置
    • Cookies
    • 处理装饰器
    • 流
    • 基于类的视图
    • 自定义协议
    • SSL 例子
    • 日志
    • 测试
    • 部署
    • 扩展
    • 贡献
    • API Reference
  • Python

  • backend
  • Sanic
devin
2023-09-07

蓝图

# 蓝图

蓝图 (Blueprints) 是用在一个应用程序里可用作子路由的对象。作为添加路由到应用程序实例的替代者,蓝图为添加路由定义了相似的方法,即用一种灵活而且可插拔的方法注册到应用程序实例。

蓝图对于大型应用特别有用,当你的应用逻辑能被分解成若干个组或者责任区域。

# 我的第一个蓝图

以下展示了一个非常简单的蓝图,即在你的应用的根 url / 注册了一个处理程序。

假设你保存了这个一会儿能被 import 到你的主应用的文件 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'})

1
2
3
4
5
6
7
8
9

# 注册蓝图

蓝图必须被应用程序注册。

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)
1
2
3
4
5
6
7

这将会添加蓝图到应用程序并且注册任意的被蓝图定义的路由。在 app.router 里已经注册的路由看起来如下:

[Route(handler=<function bp_root at 0x7f908382f9d8>, methods=None, pattern=re.compile('^/$'), parameters=[])]
1

# 蓝图 组 和 嵌套

蓝图也可能作为一个列表或元组的部分进行注册,其中注册员将递归地遍历蓝图的任何子序列并相应地注册它们。Blueprint.group 方法提供简化的程序,允许一个 '模拟' 后端目录结构模仿从前端看到的东西。考虑这个 (颇有认为的) 例子:

api/
├──content/
│  ├──authors.py
│  ├──static.py
│  └──__init__.py
├──info.py
└──__init__.py
app.py
1
2
3
4
5
6
7
8

应用的蓝图的初始化层次结构如下所示:

# api/content/authors.py
from sanic import Blueprint

authors = Blueprint('content_authors', url_prefix='/authors')
1
2
3
4
# api/content/static.py
from sanic import Blueprint

static = Blueprint('content_static', url_prefix='/static')
1
2
3
4
# api/content/__init__.py
from sanic import Blueprint

from .static import static
from .authors import authors

content = Blueprint.group(assets, authors, url_prefix='/content')
1
2
3
4
5
6
7
# api/info.py
from sanic import Blueprint

info = Blueprint('info', url_prefix='/info')
1
2
3
4
# api/__init__.py
from sanic import Blueprint

from .content import content
from .info import info

api = Blueprint.group(content, info, url_prefix='/api')
1
2
3
4
5
6
7

在 app.py 中注册这些蓝图现在可以这样完成:

# app.py
from sanic import Sanic

from .api import api

app = Sanic(__name__)

app.blueprint(api)
1
2
3
4
5
6
7
8

# 使用蓝图

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

# WebSocket 路由

WebSocket 处理程序能够使用 @bp.websocket 装饰器或者 bp.add_websocket_route 方法在蓝图注册。

# 中间件

使用蓝图允许你可以全局地注册中间件。

@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')
1
2
3
4
5
6
7
8
9
10
11

# 异常

异常可以被专门用于全局的蓝图。

@bp.exception(NotFound)
def ignore_404s(request, exception):
	return text("Yep, I totally found the page: {}".format(request.url))
1
2
3

# 静态文件

静态文件可以在蓝图前缀下全局提供。


# 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
2
3
4
5
6
7
8

# 启动和停止

蓝图可以在服务器启动和停止程序期间运行程序。如果在多进程模式 (多于一个 worker) 运行,他们会在 workers fork 之后被触发。

有效的事件如下:

  • 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()
1
2
3
4
5
6
7
8
9
10

# 用例: API 版本

蓝图能很好的用于 API 版本,一个蓝图可以指向 /v1/<routes>,另一个指向 /v2/<routes>。

当一个蓝图初始化了,它可以带一个可选的 url_prefix 参数,该参数将被添加到所有在蓝图定义的路由中。这个功能可以被用来执行我们的 API 版本方案。

# blueprints.py
from sanic.response import text
from sanic import Blueprint

blueprint_v1 = Blueprint('v1', url_prefix='/v1')
blueprint_v2 = Blueprint('v2', url_prefix='/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')
1
2
3
4
5
6
7
8
9
10
11
12
13
14

当我们在 app 上注册了我们的蓝图,这些路由 /v1 和 /v2 现在将指向独立的蓝图,允许为每一个 API 版本创建 子站点

# main.py
from sanic import Sanic
from blueprints import blueprint_v1, blueprint_v2

app = Sanic(__name__)
app.blueprint(blueprint_v1, url_prefix='/v1')
app.blueprint(blueprint_v2, url_prefix='/v2')

app.run(host='0.0.0.0', port=8000, debug=True)
1
2
3
4
5
6
7
8
9

# 用 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/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))
1
2
3
4
5
6
7
8
9
编辑 (opens new window)
上次更新: 2023/09/07, 12:09:00
中间件 和 监听器
WebSocket

← 中间件 和 监听器 WebSocket→

Theme by Vdoing | Copyright © 2023-2023 devin | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式