人财事物信息化 - Jinja for Frappe
Jinja基础知识(Frappe开发视角)
- 定位与核心作用
- 基于Python的高性能模板引擎,用于动态生成HTML/XML等文档
- 在Frappe中用于渲染页面模板、邮件内容等UI层逻辑
- 基础语法
- 变量: {{ variable }} ,支持Python表达式、字典/对象属性访问
- 控制结构:
- 条件: {% if condition %}...{% endif %}
- 循环: {% for item in list %}...{% endfor %} ,支持 loop.index 等内置变量
- 模板继承: {% extends "base.html" %} + {% block content %}...{% endblock %}
- 过滤器与测试:
- 过滤器: {{ name|upper }} (转换大写)、 {{ date|format("%Y-%m-%d") }}
- 测试: {% if value is defined %} 、 {% if list is empty %}
- 转义与安全:默认自动转义HTML,可通过 |safe 禁用
- 关键特性(Frappe适配点)
- 上下文变量:Frappe可注入文档对象(如 doc )、用户权限等上下文
- 自定义扩展:支持开发自定义过滤器/测试/全局函数,适配业务逻辑
- 沙箱模式:通过 SandboxedEnvironment 限制危险操作,保障安全性
- 与Frappe集成要点
- 模板文件路径:通常存于 apps/[app_name]/templates/ 目录
- 数据传递:通过 frappe.render_template 传入上下文数据
- 与Python代码解耦:避免复杂逻辑写入模板,保持MVC分层
框架脑图(极简版)
Jinja模板引擎
├─ 基础语法
│ ├─ 变量插值 {{ }}
│ ├─ 控制结构 {% %}
│ ├─ 模板继承 extends/block
│ └─ 过滤器/测试 |is
├─ 核心功能
│ ├─ 自动转义(安全机制)
│ ├─ 上下文管理(数据注入)
│ ├─ 自定义扩展(过滤器/函数)
│ └─ 沙箱环境(限制执行)
├─ Frappe集成
│ ├─ 模板路径规范
│ ├─ 数据传递方式
│ └─ 安全模式应用
└─ 开发最佳实践
├─ 避免复杂逻辑入模板
├─ 善用继承减少重复代码
└─ 结合Frappe API处理业务
注:如需深入某部分(如自定义扩展或Frappe具体集成案例),可进一步补充说明。
为实现符合中国会计司规范的凭证、账簿、报表格式,需重点掌握Jinja以下功能,结合会计格式的特殊性(如金额分位、中文大写、多页排版、签章位置等)进行适配:
一、格式控制核心功能
- 精确文本格式化(数字/日期)
- 数字格式化:
- 金额千位分隔: {{ amount|number_format }} (默认逗号分隔,可自定义符号)。
- 固定小数位: {{ amount|round(2) }} (保留两位小数,适配人民币精度)。
- 中文大写金额:需自定义过滤器(如 |tochineseuppercase ),结合Python模块(如 cn2an )实现 1234.56 → 壹仟贰佰叁拾肆元伍角陆分 。
- 日期格式化:
- 标准日期格式: {{ date|strftime("%Y年%m月%d日") }} (适配“2025年06月07日”格式)。
- 表格与多列布局
- 循环生成表格行:
<table>
<tr>
<th>科目名称</th>
<th>借方金额</th>
<th>贷方金额</th>
</tr>
{% for item in entries %}
<tr>
<td>{{ item.account }}</td>
<td>{{ item.debit|number_format }}</td>
<td>{{ item.credit|number_format }}</td>
</tr>
{% endfor %}
</table>
- 多页表格续表:需结合CSS分页( @page )或PDF生成工具(如 reportlab ),通过Jinja变量控制页码和表头重复。
- 特殊符号与对齐
- 人民币符号固定前置: {{ "¥" ~ amount|number_format }} (注意符号与数字间无空格)。
- 借贷方金额对齐:利用CSS text-align: right 或Jinja填充字符(如 {{ amount|string.format("%10.2f") }} 左补空格)。
二、布局与打印适配
- 模板继承与分页
- 定义通用会计模板:
{% extends "accounting_base.html" %}
{% block header %}
记账凭证
凭证编号:{{ voucher_no }}
日期:{{ date|strftime("%Y年%m月%d日") }}
{% endblock %}
{% block content %}
<!-- 具体分录内容 -->
{% endblock %}
{% block footer %}
制单人:{{ user }} 复核人:{{ checker }}
第{{ page }}页,共{{ total_pages }}页
{% endblock %}
- 分页控制:通过Python计算总页数,传入Jinja变量 total_pages ,结合 {% if page == 1 %}{% endif %} 控制首页/续页差异(如首页显示表头,续页隐藏标题但重复表头行)。
- 签章与水印
- 图片嵌入:使用
<img src="{{ static_path }}/签章.png" style="width: 80px;">
插入电子签章图片(需确保路径在Frappe中可访问)。 - 水印背景:通过CSS background-image 属性添加“机密”“原件”等水印,Jinja可动态控制水印文本(如 {% if is_draft %}草稿{% else %}正式{% endif %} )。
三、数据校验与安全
- 平衡校验逻辑
- 在模板中添加借贷方合计校验提示(非核心逻辑建议放后端):
{% set total_debit = entries|sum(attribute='debit') %}
{% set total_credit = entries|sum(attribute='credit') %}
{% if total_debit != total_credit %}
<div style="color: red;">警告:借贷方金额不平衡!</div>
{% endif %}
- 沙箱模式与权限控制
- 使用Jinja的 sandboxed=True 环境,禁止执行危险操作(如文件读写),确保会计数据安全。
- 结合Frappe权限系统,控制模板中敏感字段可见性(如 {% if has_permission('Account', 'read', doc) %}{{ doc.balance }}{% endif %} )。
四、自定义扩展开发
- 自定义过滤器
- 中文大写金额过滤器:
# 在Frappe中注册自定义过滤器
from jinja2 import Environment
from cn2an import cn2an # 需安装cn2an库
def to_chinese_uppercase(number):
integer_part, decimal_part = str(number).split('.')
integer_cn = cn2an.integer2cn(int(integer_part), mode='traditional')
decimal_cn = cn2an.integer2cn(int(decimal_part), mode='simple')
return f"{integer_cn}元{decimal_cn}角" # 简化逻辑,需处理角分零值
env = Environment()
env.filters['to_chinese_uppercase'] = to_chinese_uppercase
- 金额分位符自定义:覆盖默认 numberformat 过滤器,支持中文逗号/点号分隔(如 {{ amount|localizednumber_format(",", ".") }} )。
- 全局函数集成
- 在Frappe中通过 frappe.jinja_globals 注入会计专用函数,例如:
# 在Frappe应用的__init__.py中配置
frappe.jinja_globals.update({
'get_account_name': get_account_name_from_code, # 根据科目代码获取名称
'calculate_tax': calculate_vat # 计算增值税
})
模板中调用: {{ getaccountname(entry.account_code) }} 。
五、与会计数据对接
- 上下文数据结构设计
- 定义符合会计凭证的数据结构(如 entries 列表包含科目、借贷方、金额、摘要等字段),确保Jinja模板可直接访问:
data = {
"voucher_no": "2025-001",
"date": datetime.date(2025, 6, 7),
"entries": [
{"account": "库存现金", "debit": 1000.00, "credit": 0.00, "remark": "销售收款"},
{"account": "主营业务收入", "debit": 0.00, "credit": 1000.00, "remark": ""}
]
}
- 多语言与本地化
- 处理中文表头(如“借方金额”“贷方金额”),配合Frappe的多语言功能,通过 {{ _("Debit") }} 动态切换中英文(需在模板中启用i18n扩展)。
关键工具链建议
- PDF生成:结合 wkhtmltopdf 或 xhtml2pdf 将Jinja渲染的HTML转为符合会计归档要求的PDF(需处理分页、字体嵌入问题,如中文字体需指定 SimSun 等)。
- 电子签章:集成CA证书接口,通过Jinja动态插入签章图片URL或二维码(需与电子档案系统对接)。
通过以上功能组合,可实现符合《会计信息化发展规划(2021-2025年)》要求的电子化会计凭证、账簿和报表格式。