8.2 KiB
8.2 KiB
模板引擎技术文档
简介
MyTemplateEngine 是一个基于 Jinja2 的轻量级模板渲染引擎,支持文件和字符串模板的渲染、变量注入、JSON 数据加载以及自定义全局函数。该模块封装了常用的文件路径处理、类型转换、数据访问等功能,适用于配置生成、报告输出、代码模板等场景。
功能特性
- ✅ 支持从字符串或文件加载模板
- ✅ 支持多路径模板搜索(通过
pathList) - ✅ 内置常用工具函数(如
json,hasattr, 类型转换等) - ✅ 提供便捷的 JSON 文件与模板结合渲染功能
- ✅ 自动处理跨平台路径分隔符
- ✅ 可扩展的全局变量/函数注入机制
- ✅ 支持 UTF-8 编码输入输出(可配置)
安装依赖
pip install jinja2 ujson apppublic
注:
appPublic.argsConvert和appPublic.dictObject来自第三方包apppublic,需确保已安装。
模块导入说明
import os
import sys
try:
import ujson as json # 更快的 JSON 解析器
except ImportError:
import json # 标准库回退
from jinja2 import Environment, FileSystemLoader, BaseLoader, meta
import codecs
from appPublic.argsConvert import ArgsConvert
from appPublic.dictObject import DictObject
公共函数
isNone(obj) -> bool
判断对象是否为 None。
参数:
obj: 任意对象
返回值:
True如果obj是None,否则False
string_template_render(tmp_string: str, data: dict) -> str
使用字典数据渲染字符串模板。
参数:
tmp_string: Jinja2 风格的模板字符串data: 渲染所需的数据字典
示例:
result = string_template_render("Hello {{ name }}!", {"name": "Alice"})
# 输出: Hello Alice!
类:MyTemplateEngine
主模板引擎类,封装了完整的模板解析与渲染能力。
构造函数:__init__(pathList, file_coding='utf-8', out_coding='utf-8', env={})
初始化模板引擎实例。
参数:
| 参数名 | 类型 | 说明 |
|---|---|---|
pathList |
str 或 list |
模板文件搜索路径列表(支持单个路径或路径列表) |
file_coding |
str |
模板文件读取编码,默认 'utf-8' |
out_coding |
str |
输出编码(目前主要用于内部一致性,实际返回为字符串) |
env |
dict |
用户自定义注入到模板中的全局变量或函数 |
初始化行为:
- 创建
FileSystemLoader加载器,用于从指定路径加载模板。 - 初始化
Environment并注册内置函数和工具。 - 向 Jinja2 全局命名空间 (
globals) 注入以下内容:
| 名称 | 类型 | 用途 |
|---|---|---|
json |
module | 提供 json.dumps/json.loads |
hasattr |
built-in | 判断对象是否有某属性 |
int, float, str, type, len |
built-in | 基础类型与操作 |
isNone |
function | 判断是否为 None |
render |
method | 调用当前引擎渲染模板文件 |
renders |
method | 渲染模板字符串 |
ArgsConvert |
class | 参数转换工具类 |
renderJsonFile |
method | 快捷方法:用 JSON 文件数据渲染模板 |
ospath(x) |
lambda | 统一路径分隔符(适应 Windows/Linux) |
basename(x) |
lambda | 获取路径中的文件名部分 |
basenameWithoutExt(x) |
lambda | 获取无扩展名的文件名 |
extname(x) |
lambda | 获取文件扩展名 |
示例:
te = MyTemplateEngine(['/templates', '/shared'], file_coding='utf-8')
方法:get_template_variables(tmpl: str) -> list[str]
分析模板字符串中所有未声明但使用的变量名。
参数:
tmpl: Jinja2 模板字符串
返回值:
- 所有在模板中引用但未定义的变量名列表(可用于调试或预检)
示例:
vars = te.get_template_variables("Hello {{ user.name }}! You have {{ count }} messages.")
# 返回: ['user', 'count']
方法:set(k: str, v: Any)
向模板上下文注入全局变量或函数。
参数:
k: 变量名(字符串)v: 值或可调用对象
⚠️ 注意:此操作会影响后续所有模板渲染。
示例:
te.set('site_name', 'MySite')
te.set('now', lambda: datetime.now())
方法:_render(template: Template, data: dict) -> str
内部方法:执行模板渲染。
参数:
template: 已加载的 Jinja2Template对象data: 数据字典
返回值:
- 渲染后的字符串
方法:renders(tmplstring: str, data: dict) -> str
渲染模板字符串。
参数:
tmplstring: Jinja2 模板字符串data: 渲染数据
特性:
- 将传入的
data包装成global()函数注入模板,允许在模板中通过global()访问原始数据结构。
示例模板:
User: {{ global().user.name }}
Total: {{ len(global().items) }}
使用示例:
output = te.renders("Hello {{ name }}!", {"name": "Bob"})
方法:render(tmplfile: str, data: dict) -> str
渲染指定路径的模板文件。
参数:
tmplfile: 模板文件相对或绝对路径(将在pathList中查找)data: 渲染数据字典
示例:
with open('data.json') as f:
data = json.load(f)
result = te.render('email_template.html', data)
方法:renderJsonFile(tmplfile: str, jsonfile: str) -> str
快捷方法:使用 JSON 文件中的数据渲染模板文件。
参数:
tmplfile: 模板文件路径jsonfile: JSON 数据文件路径
行为:
- 读取并解析
jsonfile - 使用其内容作为上下文调用
render(tmplfile, data)
示例:
output = te.renderJsonFile('report.html', 'data.json')
辅助函数:tmpTml(f: str, ns: dict) -> str
将模板文件渲染后保存至 /tmp/ 目录,并返回生成文件的路径。
参数:
f: 模板文件路径ns: 数据上下文字典
返回值:
- 生成的临时文件完整路径(例如
/tmp/report.html)
流程:
- 创建
MyTemplateEngine实例,搜索路径为当前目录. - 读取模板内容
- 渲染模板
- 写入
/tmp/<原文件名> - 返回文件路径
示例:
temp_path = tmpTml('template.txt', {'name': 'Test'})
print(f"Generated at: {temp_path}")
命令行使用
当直接运行此脚本时,支持命令行调用:
python template_engine.py <template_file> <json_data_file>
示例:
python template_engine.py hello.tmpl.json data.json
程序会:
- 读取模板文件
- 加载 JSON 数据
- 渲染并输出结果到标准输出
若参数不足,打印用法提示并退出。
模板语法示例(Jinja2)
<!DOCTYPE html>
<html>
<head><title>{{ title }}</title></head>
<body>
<h1>Welcome, {{ user.name }}!</h1>
<p>You have {{ len(messages) }} messages.</p>
{% if not isNone(subtitle) %}
<h2>{{ subtitle }}</h2>
{% endif %}
<p>File: {{ basenameWithoutExt(global().input_file) }} (Ext: {{ extname(global().input_file) }})</p>
</body>
</html>
编码说明
- 所有文件读写均使用
codecs.open(..., encoding='utf-8') - 默认编码可由构造函数设置
- 推荐统一使用 UTF-8 编码避免乱码问题
错误处理建议
| 异常类型 | 建议措施 |
|---|---|
TemplateNotFound |
检查 pathList 是否包含目标模板路径 |
UnicodeDecodeError |
确保文件真实编码与 file_coding 一致 |
JSONDecodeError |
验证 JSON 文件格式正确 |
UndefinedError |
使用 get_template_variables() 检查缺失变量 |
扩展建议
可通过 env 参数或 set() 方法添加更多工具函数,例如:
te.set('upper', str.upper)
te.set('today', lambda: datetime.today().strftime('%Y-%m-%d'))
也可集成 DictObject 实现更灵活的数据访问。
版权与许可
© 2025 Your Company. 开源项目,请保留原作者信息。
使用遵循 MIT License(除非另有声明)。