人财事物信息化 - Jinja for Frappe

Jinja基础知识(Frappe开发视角)

  1. 定位与核心作用
  • 基于Python的高性能模板引擎,用于动态生成HTML/XML等文档
  • 在Frappe中用于渲染页面模板、邮件内容等UI层逻辑
  1. 基础语法
  • 变量: {{ 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 禁用
  1. 关键特性(Frappe适配点)
  • 上下文变量:Frappe可注入文档对象(如 doc )、用户权限等上下文
  • 自定义扩展:支持开发自定义过滤器/测试/全局函数,适配业务逻辑
  • 沙箱模式:通过 SandboxedEnvironment 限制危险操作,保障安全性
  1. 与Frappe集成要点
  • 模板文件路径:通常存于 apps/[app_name]/templates/ 目录
  • 数据传递:通过 frappe.render_template 传入上下文数据
  • 与Python代码解耦:避免复杂逻辑写入模板,保持MVC分层

框架脑图(极简版)

Jinja模板引擎
├─ 基础语法
│  ├─ 变量插值 {{ }}
│  ├─ 控制结构 {% %}
│  ├─ 模板继承 extends/block
│  └─ 过滤器/测试 |is
├─ 核心功能
│  ├─ 自动转义(安全机制)
│  ├─ 上下文管理(数据注入)
│  ├─ 自定义扩展(过滤器/函数)
│  └─ 沙箱环境(限制执行)
├─ Frappe集成
│  ├─ 模板路径规范
│  ├─ 数据传递方式
│  └─ 安全模式应用
└─ 开发最佳实践
   ├─ 避免复杂逻辑入模板
   ├─ 善用继承减少重复代码
   └─ 结合Frappe API处理业务

注:如需深入某部分(如自定义扩展或Frappe具体集成案例),可进一步补充说明。

为实现符合中国会计司规范的凭证、账簿、报表格式,需重点掌握Jinja以下功能,结合会计格式的特殊性(如金额分位、中文大写、多页排版、签章位置等)进行适配:

一、格式控制核心功能

  1. 精确文本格式化(数字/日期)
  • 数字格式化:
  • 金额千位分隔: {{ amount|number_format }} (默认逗号分隔,可自定义符号)。
  • 固定小数位: {{ amount|round(2) }} (保留两位小数,适配人民币精度)。
  • 中文大写金额:需自定义过滤器(如 |tochineseuppercase ),结合Python模块(如 cn2an )实现 1234.56 → 壹仟贰佰叁拾肆元伍角陆分 。
  • 日期格式化:
  • 标准日期格式: {{ date|strftime("%Y年%m月%d日") }} (适配“2025年06月07日”格式)。
  1. 表格与多列布局
  • 循环生成表格行:
<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变量控制页码和表头重复。
  1. 特殊符号与对齐
  • 人民币符号固定前置: {{ "¥" ~ amount|number_format }} (注意符号与数字间无空格)。
  • 借贷方金额对齐:利用CSS text-align: right 或Jinja填充字符(如 {{ amount|string.format("%10.2f") }} 左补空格)。

二、布局与打印适配

  1. 模板继承与分页
  • 定义通用会计模板:
{% 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 %} 控制首页/续页差异(如首页显示表头,续页隐藏标题但重复表头行)。
  1. 签章与水印
  • 图片嵌入:使用<img src="{{ static_path }}/签章.png" style="width: 80px;">插入电子签章图片(需确保路径在Frappe中可访问)。
  • 水印背景:通过CSS background-image 属性添加“机密”“原件”等水印,Jinja可动态控制水印文本(如 {% if is_draft %}草稿{% else %}正式{% endif %} )。

三、数据校验与安全

  1. 平衡校验逻辑
  • 在模板中添加借贷方合计校验提示(非核心逻辑建议放后端):
{% 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 %}
  1. 沙箱模式与权限控制
  • 使用Jinja的 sandboxed=True 环境,禁止执行危险操作(如文件读写),确保会计数据安全。
  • 结合Frappe权限系统,控制模板中敏感字段可见性(如 {% if has_permission('Account', 'read', doc) %}{{ doc.balance }}{% endif %} )。

四、自定义扩展开发

  1. 自定义过滤器
  • 中文大写金额过滤器:
# 在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(",", ".") }} )。
  1. 全局函数集成
  • 在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) }} 。

五、与会计数据对接

  1. 上下文数据结构设计
  • 定义符合会计凭证的数据结构(如 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": ""}
    ]
}
  1. 多语言与本地化
  • 处理中文表头(如“借方金额”“贷方金额”),配合Frappe的多语言功能,通过 {{ _("Debit") }} 动态切换中英文(需在模板中启用i18n扩展)。

关键工具链建议

  • PDF生成:结合 wkhtmltopdf 或 xhtml2pdf 将Jinja渲染的HTML转为符合会计归档要求的PDF(需处理分页、字体嵌入问题,如中文字体需指定 SimSun 等)。
  • 电子签章:集成CA证书接口,通过Jinja动态插入签章图片URL或二维码(需与电子档案系统对接)。

通过以上功能组合,可实现符合《会计信息化发展规划(2021-2025年)》要求的电子化会计凭证、账簿和报表格式。

Discard
Save
Review Changes ← Back to Content
Message Status Space Raised By Last update on