Skip to content

模板

Starlette 并非严格与任何特定的模板引擎耦合,但 Jinja2 是一个极好的选择。

Jinja2 模板

签名: Jinja2Templates(directory, context_processors=None, **env_options)

  • directory - 一个字符串、os.Pathlike 或一个字符串或 os.Pathlike 的列表,表示一个目录路径。
  • context_processors - 一系列返回字典以添加到模板上下文的函数的列表。
  • **env_options - 传递给 Jinja2 环境的其他关键字参数。

Starlette 提供了一种简单的方法来进行 jinja2 配置。这可能是您默认想要使用的。

from starlette.applications import Starlette
from starlette.routing import Route, Mount
from starlette.templating import Jinja2Templates
from starlette.staticfiles import StaticFiles


templates = Jinja2Templates(directory='templates')

async def homepage(request):
    return templates.TemplateResponse(request, 'index.html')

routes = [
    Route('/', endpoint=homepage),
    Mount('/static', StaticFiles(directory='static'), name='static')
]

app = Starlette(debug=True, routes=routes)

请注意,传入的 request 实例必须作为模板上下文的一部分包含在内。

Jinja2 模板上下文将自动包含一个 url_for 函数,因此我们可以在应用程序内正确地超链接到其他页面。

例如,我们可以从我们的 HTML 模板内部链接到静态文件:

<link href="{{ url_for('static', path='/css/bootstrap.min.css') }}" rel="stylesheet" />

如果您想要使用自定义过滤器,您将需要更新 Jinja2Templatesenv 属性:

from commonmark import commonmark
from starlette.templating import Jinja2Templates

def marked_filter(text):
    return commonmark(text)

templates = Jinja2Templates(directory='templates')
templates.env.filters['marked'] = marked_filter

使用自定义的 jinja2.Environment 实例

Starlette 也接受一个预先配置的 jinja2.Environment 实例。

import jinja2
from starlette.templating import Jinja2Templates

env = jinja2.Environment(...)
templates = Jinja2Templates(env=env)

上下文处理器

上下文处理器是一个函数,它返回一个字典以合并到模板上下文中。每个函数仅接受一个参数 request ,并且必须返回一个要添加到上下文中的字典。

模板处理器的一个常见用例是使用共享变量扩展模板上下文。

import typing
from starlette.requests import Request

def app_context(request: Request) -> typing.Dict[str, typing.Any]:
    return {'app': request.app}

注册上下文模板

将上下文处理器传递给 Jinja2Templates 类的 context_processors 参数。

import typing

from starlette.requests import Request
from starlette.templating import Jinja2Templates

def app_context(request: Request) -> typing.Dict[str, typing.Any]:
    return {'app': request.app}

templates = Jinja2Templates(
    directory='templates', context_processors=[app_context]
)

!!! 信息 作为上下文处理器的异步函数不受支持。

测试模板响应

在使用测试客户端时,模板响应包括 .template.context 属性。

from starlette.testclient import TestClient


def test_homepage():
    client = TestClient(app)
    response = client.get("/")
    assert response.status_code == 200
    assert response.template.name == 'index.html'
    assert "request" in response.context

定制 Jinja2 环境

Jinja2Templates 接受 Jinja2 Environment 支持的所有选项。这将允许对 Starlette 创建的 Environment 实例进行更多控制。

对于 Environment 可用的选项列表,您可以在此处查看 Jinja2 文档

from starlette.templating import Jinja2Templates


templates = Jinja2Templates(directory='templates', autoescape=False, auto_reload=True)

异步模板渲染

Jinja2 支持异步模板渲染,然而一般来说,我们建议您使您的模板避免包含调用数据库查找或其他 I/O 操作的逻辑。

相反,我们建议您确保您的端点执行所有的 I/O,例如,在视图内严格评估任何数据库查询,并将最终结果包含在上下文中。