# Version 21.6

# 介绍(Introduction)

这是 21 版本发布周期内的第二次发布。我们将在 12 月份发布长期支持办,在此之前,我们还会在 9 月还会进行一次发布。值得注意的是,在 21.3 版本中,路由已经被作为依赖被移动到了单独的包中: sanic-routing (opens new window)。这一变化可能会暂时保留。从这个版本开始,路由最低要求的版本是0.7.0。

# 更新内容(What to know)

更多细节详见发布说明 (opens new window)。以下是值得注意的新功能或突破性变化,以及更新内容...

# 弃用 StreamingHTTPResponse (Deprecation of StreamingHTTPResponse)

StreamingHTTPResponse 已经被弃用,并将在 21.12 版本中删除。这将影响 sanic.response.streamsanic.response.file_stream 方法,它们都依赖 StreamingHTTPResponse 对象。

尽管确切的迁移路线还没有确认,但是 sanic.response.streamsanic.response.file_stream 将继续以某种便捷操作的形式继续存在于 v21.12 中。我们希望经历一个夏天的讨论,在 9 月的发布前确定更多细节。

# 弃用 CompositionView(Deprecation of CompositionView)

CompositionView 已经被弃用,并且将在 21.12 版本中删除。

# 弃用路径参数类型: stringnumber (Deprecation of path parameter types: string and number)

今后,您应该使用 strfloat 作为路径参数类型来替代原先的 stringnumber

@app.get("/<foo:str>/<bar:float>")
async def handler(request, foo: str, bar: float):
    ...

现有的 stringnumber 类型将作为新类型的别名,但将在v21.12中被删除。

# 升级至0.7版本的路由(Version 0.7 router upgrades)

在0.7版本中,修复了一些列 bug,并且相比 0.6 版本,新版本能优雅地处理更多的边缘情况。如果您遇到任何不支持的路由模式,请在这里反馈 (opens new window)。您可以在 sanic-routing 发布说明 (opens new window)中看到一些问题的解决。

# 使用 eof() 来结束流式传输(Inline streaming with eof())

我们在 21.3 中对处理流式传输进行了重大变更 (opens new window),并且提供了新的串流方式。为了提供进一步的便利,我们在 21.6 中加入了一个新的 response.eof() 方法来结串流。一旦所有的数据被推送到客户端,就该调用该方法。

@app.route("/")
async def test(request):
    response = await request.respond(content_type="text/csv")
    await response.send("foo,")
    await response.send("bar")
    await response.eof()
    return response

# 新的路径参数类型 slug (New path parameter type: slug)

您现在可以使用 slug 类型来指定一段动态的路径并进行适当的匹配。

@app.get("/articles/<article_slug:slug>")
async def article(request, article_slug: str):
    ...

slug 必须由小写字母或数字组成。它可以包含多个连字符(-),但它不能放在开头。

this-is-a-slug
with-123-is-also-a-slug
111-at-start-is-a-slug
NOT-a-slug
-NOT-a-slug

# 更加严格的应用蓝图名称,弃用随意的命名方式(Stricter application and blueprint names, and deprecation)

您的应用和蓝图实例必须符合一套更严格命名的要求。

  1. 只能由字母数字字符组成
  2. 可以包含一个连字符(-)或下划线(_
  3. 必须以一个字母开头(大写或小写)

这样的命名规则类似于 Python 的变量命名规则,但增加了允许连字符(-)。

较随意的命名标准已被废除。从 21.12 开始,不符合标准的名称将会导致一个运行时的错误。

# Route 对象的 route.uri 新属性 (A new access on Route object: route.uri)

v21.3 中的 Route 对象不再有 uri 属性。取而代之的是 route.path 。然而,由于 sanic-routing 的工作方式,path 属性 不能 再以斜杠 / 开头。所以现在设置以斜杠开头的 route.uri 属性来作为补充。

route.uri == f"/{route.path}"

# Request 对象包含ip信息的新属性(A new accessor on Request object impacting IPs)

Request 对象上有一个 request.ip 属性能很方便地获取请求的 IP 信息。这个属性值来自另一个包含了更多 HTTP 连接细节的底层对象:request.conn_info

目前的版本为 conn_info 对象增加了一个新的 client_ip 属性。对于 IPv4 ,您不会注意到有什么不同。然而,对于 IPv6 的应用,新的属性将提供一个“无包装”的地址版本。请看下面的例子:

@app.get("/")
async def handler(request):
    return json(
        {
            "request.ip": request.ip,
            "request.conn_info.client": request.conn_info.client,
            "request.conn_info.client_ip": request.conn_info.client_ip,
        }
    )
app.run(sock=my_ipv6_sock)
$ curl http://\[::1\]:8000
{
  "request.ip": "::1",
  "request.conn_info.client": "[::1]",
  "request.conn_info.client_ip": "::1"
}

# 可选的 ConfigSanic.ctx 对象 (Alternate Config and Sanic.ctx objects)

您现在可以为 Sanic 应用传入自定义的配置和上下文对象。自定义的配置应该sanic.config.Config 的子类。上下文则可以被设置为任何对象,没有限制。

class CustomConfig(Config):
    ...
config = CustomConfig()
app = Sanic("custom", config=config)
assert isinstance(app.config, CustomConfig)

和:

class CustomContext:
    ...
ctx = CustomContext()
app = Sanic("custom", ctx=ctx)
assert isinstance(app.ctx, CustomContext)

# Sanic 命令行工具改进(Sanic CLI improvements)

  1. 现有功能新标志:--auto-reload
  2. 现有参数的的新缩写标志
  3. 新功能:--factory
  4. 新功能:--simple
  5. 新功能:--reload-dir

# 工厂应用(Factory applications)

对于遵循工厂模式(一个返回 sanic.Sanic 实例的函数)的应用程序,您可以在 Sanic 命令行工具中添加 --factory 标志来启动它。

from sanic import Blueprint, Sanic, text
bp = Blueprint(__file__)
@bp.get("/")
async def handler(request):
    return text("😎")
def create_app() -> Sanic:
    app = Sanic(__file__)
    app.blueprint(bp)
    return app

您可以使用如下命令来启动:

$ sanic path.to:create_app --factory 

# 简易服务器(Sanic Simple Server)

Sanic 命令行工具现在添加了简易模式的命令,它将启动一个 Sanic 服务并代理指定目录下的静态文件,同时也会在第一级目录中自动寻找 index.html 文件。

$ sanic ./path/to/dir --simple

注意

该功能目前仍处于早期测试阶段。可能会在今后的版本中更改。

# 指定额外的重启监听目录(Additional reload directories)

当使用 debug 或者是 auto-reload 时,您可以指定额外的目录来确保这些目录中的文件发生变动时重启 Sanic 应用。

sanic ... --reload-dir=/path/to/foo --reload-dir=/path/to/bar

提示

不需要指定应用所在的目录。Sanic 将会自动的检测应用目录下 Python 文件的变化并重启。您应该使用 reload-dir 参数来指定其他您关心的静态文件,并且在这些文件变化时通知应用重启。

# 版本前缀(Version prefix)

当使用了 version 参数时,您的路由会自动添加 /v<YOUR_VERSION_NUM> 的前缀。这并不是新的功能。

# /v1/my/path
app.route("/my/path", version=1)

现在,您可以通过在版本信息之前添加额外的路径信息的方式来可以修改这个固定前缀。

# /api/v1/my/path
app.route("/my/path", version=1, version_prefix="/api/v")

version_prefix 参数可以这么使用:

  • 使用 app.routebp.route 装饰器(以及所有其他装饰器)时
  • 创建 Blueprint 对象时
  • 调用 Blueprint.group 函数时
  • 创建 BlueprintGroup 对象时
  • 使用 app.blueprint 注册蓝图时

# 信号事件的自动注册(Signal event auto-registration)

将配置项 config.EVENT_AUTOREGISTER 设置为 True 时将允许您等待任何的信号事件,即使这些信号没有被注册到一个响应函数上。

@app.signal("do.something.start")
async def signal_handler():
    await do_something()
    await app.dispatch("do.something.complete")
# somethere else in your app:
await app.event("do.something.complete")

# 可重复利用和可嵌套的 BlueprintBlueprintGroup (Infinitely reusable and nestable Blueprint and BlueprintGroup)

单独的 Blueprint 可能不会被多个蓝图组重复注册。但是蓝图组本身可以被循环嵌套至一个或多个其他组。这将消除了蓝图组构成方式的限制。

# HTTP 方法作为 Enum (HTTP methods as Enum)

Sanic 现在设置了 sanic.HTTPMethodEnum 枚举对象。它可以与字符串交替使用。

from sanic import Sanic, HTTPMethod
@app.route("/", methods=["post", "PUT", HTTPMethod.PATCH])
async def handler(...):
    ...

# 拓展 HTTPMethodView (Expansion of HTTPMethodView)

基于类的视图现在拥有以下三种关联app的方式:

方式1 - 现有的

class DummyView(HTTPMethodView):
    ...
app.add_route(DummyView.as_view(), "/dummy")

方式2 - 使用 attach 方法关联

class DummyView(HTTPMethodView):
    ...
DummyView.attach(app, "/")

方式3 - 定义类时使用 __init_subclass__ 方法关联

class DummyView(HTTPMethodView, attach=app, uri="/"):
    ...

如果您您的视图定义在其他文件中,方式2和方式3将会比较有用:

from sanic import Sanic, HTTPMethodView
class DummyView(HTTPMethodView, attach=Sanic.get_app(), uri="/"):
    ...

# 新闻(News)

# Discord 聊天室和社区论坛 (Discord and support forums)

如果您还没有加入我们的社区,您可以通过加入Discord服务器 (opens new window)社区论坛 (opens new window)来参与社区讨论。此外,别忘了在Twitter上关注@sanicframework (opens new window)

# Sanic 社区组织 2022 年选举(SCO 2022 elections)

这个 夏天🏝 / 冬天❄️(根据您所在的半球)即将来临。这意味着我们将举行 Sanic 社区组织的选举。今年,我们将有以下职位需要填补:

  • 指导委员会成员 (任期2年)
  • 指导委员会成员(任期2年)
  • 指导委员会成员(任期1年)
  • v22版本发布经理
  • v22版本发布经理

@vltr (opens new window) 将继续担任指导委员会,完成他第二年的工作。

如果您有兴趣了解更多信息,您可以阅读有关 SCO 角色和责任 或在 Discord 上的找 Adam Hopkins 了解详细情况。

提名将于 9 月 1 日开始。随着选举的来临,更多的信息将在论坛上发布。

# 正在进行的新项目(New project underway)

我们在 SCO 的名下增加了一个新项目:sanic-ext (opens new window)。该项目尚未发布,并处于积极开发中。这个项目的目标是最终取代sanic-openapi (opens new window),为 Web 应用开发者提供更多的功能,包括参数校验、CORS 和 HTTP自动响应。如果您有兴趣帮忙,请在 Discord 上告诉我们。我们希望在 9 月份的发布之前看到该项目的初始版本。

# 鸣谢(Thank you)

感谢所有参与本次发布的人:👏

@aaugustin (opens new window) @ahopkins (opens new window) @ajaygupta2790 (opens new window) @ashleysommer (opens new window) @ENT8R (opens new window) @fredlllll (opens new window) @graingert (opens new window) @harshanarayana (opens new window) @jdraymon (opens new window) @Kyle-Verhoog (opens new window) @sanjeevanahilan (opens new window) @sjsadowski (opens new window) @Tronic (opens new window) @vltr (opens new window) @ZinkLu (opens new window)


如果您喜欢本项目,请考虑参与建设本项目。我们欢迎您提交代码,也欢迎您以任何其他方式来参与本项目的建设。比如撰写文档,分享使用心得,参与社区讨论,当然,如果经济允许,您也可以考虑经济资助 (opens new window)

MIT Licensed
Copyright © 2018-present Sanic Community Organization

~ Made with ❤️ and ☕️ ~