Skip to content

本章概要

代码生成器模板的 Jinja2 语法说明,包括模板变量、字段属性和自定义模板的开发方法。

自定义模板

模板文件位于 public/templates/,使用 Jinja2 语法。修改模板后重新生成即可生效。

模板目录结构

public/templates/
├── models.py.tpl                 # ORM 模型
├── forms.py.tpl                  # Django 表单验证
├── services.py.tpl               # 业务逻辑层
├── views.py.tpl                  # 视图层
├── urls.py.tpl                   # 路由配置
├── apps.py.tpl                   # 应用配置
├── admin.py.tpl                  # 后台管理
├── ui/                           # 普通分页列表模板
│   ├── index.vue.tpl             # 主页面
│   ├── edit.vue.tpl              # 编辑弹窗
│   ├── detail.vue.tpl            # 详情弹窗
│   ├── columns.ts.tpl            # 表格列定义
│   ├── querySchemas.ts.tpl       # 搜索表单 Schema
│   └── api.ts.tpl                # API 请求封装
└── ui2/                          # 树状列表模板
    ├── index.vue.tpl             # 树形主页面
    ├── edit.vue.tpl              # 树形编辑弹窗
    ├── detail.vue.tpl            # 树形详情弹窗
    └── columns.ts.tpl            # 树形列定义

ui/ vs ui2/ 切换逻辑

当表中存在 parent_idpid 字段时,自动切换为 ui2/ 树形模板:

字段列表中是否有 parent_id / pid?
  ├── 是 -> 使用 ui2/ 模板(4 个组件 + 1 个 API)
  └── 否 -> 使用 ui/  模板(5 个组件 + 1 个 API)

两者共用 ui/api.ts.tpl 生成 API 接口文件。

模板变量

基础变量

变量类型说明示例
app_namestr模块名example
module_commentstr中文名案例
module_namestr模块名称(下划线移除)example
model_class_namestr类名Example
model_class_name_camelstr驼峰类名(首字母小写)example
route_prefixstr路由前缀example
permission_prefixstr权限前缀sys:example
display_fieldstr显示字段name
display_field_camelstr显示字段驼峰name
table_namestr数据库表名example
primary_keystr主键字段id

功能标识

变量类型说明
has_sortbool有排序字段
has_statusbool有状态字段
has_unique_codebool有唯一编码字段
has_image_fieldbool有图片字段
has_rich_text_fieldbool有富文本字段
has_exportbool有导出功能

字段列表

变量类型说明
fieldslist全部字段
form_fieldslist表单字段(in_form=True
list_fieldslist列表显示字段(in_list=True
filter_fieldslist筛选字段(filterable=True
filterable_fieldslist可过滤字段
searchable_fieldslist可搜索字段
editable_fieldslist可编辑字段

前端专用变量

变量类型说明
api_pathstrAPI 路径(如 tool/example
is_tree_structurebool是否树形结构
parent_id_fieldstr父级字段名
has_search_formbool显示搜索表单
show_selectionbool显示复选框(树形结构)
action_column_widthint操作列宽度(树形结构)

字段对象属性

fields 列表中每个字段对象包含以下属性:

基础属性

属性类型说明
namestr字段名(snake_case)
camel_namestr驼峰字段名
commentstr字段注释(原始)
labelstr清洗后的注释(去掉选项说明)
purposestr字段用途说明

类型属性

属性类型说明
typestrDjango 字段类型(CharField/IntegerField/...)
type_displaystr中文类型名
model_field_typestr模型字段类型
form_field_typestr表单字段类型
max_lengthint最大长度

约束属性

属性类型说明
nullablebool是否可空
requiredbool是否必填
is_uniquebool是否唯一
db_indexbool是否有索引
defaultany默认值

功能标识

属性类型说明
is_imagebool图片字段
is_rich_textbool富文本字段

展示控制

属性类型说明
in_formbool出现在表单中
in_listbool出现在列表中
editablebool可编辑
filterablebool作为查询条件
filter_typestr筛选类型(精确匹配/模糊查询
searchablebool可搜索

选项属性

属性类型说明
choiceslist[{value: any, label: str}, ...]
choices_namestr选项常量名
min_valueint最小值
max_valueint最大值

自定义模板示例

示例 1:为所有字段添加索引

修改 public/templates/models.py.tpl

jinja
{% if f.type == 'CharField' %}
    {{ f.name }} = models.CharField(
        max_length={{ f.max_length or 255 }},
        db_index=True,
        verbose_name="{{ f.comment }}",
        db_comment='{{ f.comment }}'
    )
{% endif %}

示例 2:自定义 Service 验证逻辑

修改 public/templates/services.py.tpl,在添加方法中添加自定义校验:

jinja
def add_{{ app_name }}(request):
    # ... 原有代码 ...
    # 自定义校验:检查名称是否重复
    if {{ model_class_name }}.objects.filter(name=cleaned_data.get('name'), is_delete=False).exists():
        return R.failed(msg="{{ module_comment }}名称已存在")
    # ... 创建记录 ...

示例 3:自定义前端表格列宽

修改 public/templates/ui/columns.ts.tpl

jinja
{% for f in list_fields %}
  {
    label: '{{ f.label }}',
    prop: '{{ f.camel_name }}',
    minWidth: {{ 80 + (f.max_length or 100) // 3 }},  {# 动态列宽 #}
  },
{% endfor %}

新增模板

如需生成额外文件(如测试文件),按以下步骤操作:

第 1 步:创建模板文件

public/templates/ 下新建 test.py.tpl

jinja
# tests/test_{{ app_name }}.py
from django.test import TestCase
from application.{{ app_name }}.models import {{ model_class_name }}


class Test{{ model_class_name }}(TestCase):
    def test_create(self):
        """测试创建{{ module_comment }}"""
        instance = {{ model_class_name }}.objects.create(
            name='测试',
            create_user='admin'
        )
        self.assertIsNotNone(instance.id)

第 2 步:注册到 backend_templates

generator_config.pygenerate() 方法中添加:

python
backend_templates = [
    'models.py.tpl',
    'forms.py.tpl',
    'services.py.tpl',
    'views.py.tpl',
    'urls.py.tpl',
    'apps.py.tpl',
    'admin.py.tpl',
    'test.py.tpl',          # 新增
]

第 3 步:调整输出路径(可选)

如果需要输出到非默认目录,修改 generate() 方法中的路径逻辑。

Jinja2 语法速查

jinja
{# 注释 #}

{# 变量输出 #}
{{ app_name }}
{{ f.name | upper }}

{# 条件判断 #}
{% if has_status %}
    # 有状态字段
{% elif has_sort %}
    # 有排序字段
{% else %}
    # 都没有
{% endif %}

{# 循环 #}
{% for f in fields %}
    {{ f.name }}
{% endfor %}

{# 循环 + 条件过滤 #}
{% for f in fields if f.is_image %}
    {{ f.name }}
{% endfor %}

{# 循环变量 #}
{% for f in fields %}
    {{ loop.index }}      {# 从 1 开始 #}
    {{ loop.first }}      {# 是否第一个 #}
    {{ loop.last }}       {# 是否最后一个 #}
{% endfor %}

{# 三元表达式 #}
{{ 'True' if f.nullable else 'False' }}

{# 字符串拼接 #}
{{ app_name }}_service

{# 默认值 #}
{{ f.max_length or 255 }}

总结

模板使用 Jinja2 语法,每个模板对应一个生成文件。模板变量包括模块名、表名、字段列表等,字段属性包含名称、类型、注释、是否可搜索等。可通过修改模板自定义生成代码的风格和结构。

小蚂蚁云团队 · 提供技术支持