掘金 后端 ( ) • 2024-04-27 18:16

theme: channing-cyan

jinja-small.png

Jinja2采用100%python代码实现,是一个现代的,设计者友好的,仿照 Django 模板的 Python 模板语言。 它速度快,被广泛使用,并且提供了可选的沙箱模板执行环境保证安全。是python界最主流的模板引擎,星星数10k+

一、环境准备

1.fastapi初始化jinja

from fastapi.templating import Jinja2Templates
# 模板初始化
jinjaEngine = Jinja2Templates(
    "template"
)

把当前目录的template文件夹作为模板引擎根目录

2.修改Jinja2的定界符

默认情况jinja是以下语法

控制结构 {% %}
变量取值 {{ }}
注释 {# #}

这个{{}}获取变量的方式,会和vue的语法冲突。所以我们需要改变这个默认的语法

custom_delimiters = {
    "variable_start_string": "[[",
    "variable_end_string": "]]",
    "block_start_string": "[%",
    "block_end_string": "%]",
    "comment_start_string": "[#",
    "comment_end_string": "#]",
}
from fastapi.templating import Jinja2Templates
# 模板初始化
jinjaEngine = Jinja2Templates(
    "template", **custom_delimiters
)

3.jinja空行去除

默认在使用语法时候会多很多的空行,比如{% %} 在解析时候会认为占位一行。需要去掉默认生成规则

from fastapi.templating import Jinja2Templates
# 模板初始化
jinjaEngine = Jinja2Templates(
    "template", trim_blocks=True, lstrip_blocks=True, **custom_delimiters
)

二、jinja的常用操作

1.使用宏复用

很多代码尤其是可能在多处使用的函数或相似的布局可以封装起来。一个好的思路就是把布局作为一个函数输出的结果

template/macro/_macros.html

[% macro user_card(list, show_bio=True) %]
<div class="user-card">
  [[ show_bio ]]
  [% if show_bio  %]
  daxin is safe.
  [% endif %]
  [# for循环 #]
  <ul>
  [% for item in list %]
    <li>[[item]]</li>
  [% endfor %]
  </ul>
</div>
[% endmacro %]
[# 引入宏模板 #]
[% import 'macro/_macros.html' as macros %]

[# 使用宏模板 #]
[[ macros.user_card(list) ]]

2.使用继承模板

类似前端的插槽,telport机制。做到一个布局占位的目的

template/extend/base.html

<!DOCTYPE html>
<html>
<head>
    <title>[% block title %]Default Title[% endblock %]</title>
</head>
<body>
    [% block content %]Default Content[% endblock %]
</body>
</html>

[# 引入继承模板 #]
[% extends "extend/base.html" %]

[# 替换继承模板 #]
[% block title %]Custom Title[% endblock %]

3.原生编译

[% raw %]
let arr =[[1],[2]]
[% endraw %]

在这里面的内容不会受到jinja的引擎控制,原样输出

三、jinja在fastapi中的使用方式

template/1.html

[% extends "extend/base.html" %]
[# 引入宏模板 #]
[% import 'macro/_macros.html' as macros %]

[# 替换继承模板 #]
[% block title %]Custom Title[% endblock %]
[% block content %]
[# 变量使用,首字母大写 #]
  [[ username|capitalize ]]
  [[ macros.user_card(list) ]]
  [[arr]]
  [# 原生编译 #]
  [% raw %]
  let arr =[[1],[2]]
  [% endraw %]
[% endblock %]

1. jinja 到浏览器

@app.get("/html")
def html(request: Request, username: str = ''):
    list = ["音乐", "游戏", "编码"]
    content = jinjaEngine.TemplateResponse(
        "1.html", {"request": request, "username": username, "list": list}
    )
    return content

2. jinja到文件

@app.get("/render")
def render():
    content = {"username": "larry", "list": ["音乐", "游戏", "编码"]}
    template = jinjaEngine.get_template("1.html")
    template.stream(content).dump("template/new_file.html")
    return content

注意生成的目录需要自己先确保存在,jinja不会帮忙创建

3. jinja原生api

from jinja2 import Template

@router.get("/renderStr")
def renderStr():
    template_str = """
    <p>Hello, {{ name }}!
    You have {{ num }} new messages.</p>
    """
    data = {
        "name": "Larry",
        "num": 3,
    }
    template=Template(template_str)
    return template.render(data)

运行项目,打开loclahost:8000/html 和 loclahost:8000/render等查看结果

image.png