Become a sponsor

本章概要
代码生成器模板的 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 # 树形列定义当表中存在 parent_id 或 pid 字段时,自动切换为 ui2/ 树形模板:
字段列表中是否有 parent_id / pid?
├── 是 -> 使用 ui2/ 模板(4 个组件 + 1 个 API)
└── 否 -> 使用 ui/ 模板(5 个组件 + 1 个 API)两者共用 ui/api.ts.tpl 生成 API 接口文件。
| 变量 | 类型 | 说明 | 示例 |
|---|---|---|---|
app_name | str | 模块名 | example |
module_comment | str | 中文名 | 案例 |
module_name | str | 模块名称(下划线移除) | example |
model_class_name | str | 类名 | Example |
model_class_name_camel | str | 驼峰类名(首字母小写) | example |
route_prefix | str | 路由前缀 | example |
permission_prefix | str | 权限前缀 | sys:example |
display_field | str | 显示字段 | name |
display_field_camel | str | 显示字段驼峰 | name |
table_name | str | 数据库表名 | example |
primary_key | str | 主键字段 | id |
| 变量 | 类型 | 说明 |
|---|---|---|
has_sort | bool | 有排序字段 |
has_status | bool | 有状态字段 |
has_unique_code | bool | 有唯一编码字段 |
has_image_field | bool | 有图片字段 |
has_rich_text_field | bool | 有富文本字段 |
has_export | bool | 有导出功能 |
| 变量 | 类型 | 说明 |
|---|---|---|
fields | list | 全部字段 |
form_fields | list | 表单字段(in_form=True) |
list_fields | list | 列表显示字段(in_list=True) |
filter_fields | list | 筛选字段(filterable=True) |
filterable_fields | list | 可过滤字段 |
searchable_fields | list | 可搜索字段 |
editable_fields | list | 可编辑字段 |
| 变量 | 类型 | 说明 |
|---|---|---|
api_path | str | API 路径(如 tool/example) |
is_tree_structure | bool | 是否树形结构 |
parent_id_field | str | 父级字段名 |
has_search_form | bool | 显示搜索表单 |
show_selection | bool | 显示复选框(树形结构) |
action_column_width | int | 操作列宽度(树形结构) |
fields 列表中每个字段对象包含以下属性:
| 属性 | 类型 | 说明 |
|---|---|---|
name | str | 字段名(snake_case) |
camel_name | str | 驼峰字段名 |
comment | str | 字段注释(原始) |
label | str | 清洗后的注释(去掉选项说明) |
purpose | str | 字段用途说明 |
| 属性 | 类型 | 说明 |
|---|---|---|
type | str | Django 字段类型(CharField/IntegerField/...) |
type_display | str | 中文类型名 |
model_field_type | str | 模型字段类型 |
form_field_type | str | 表单字段类型 |
max_length | int | 最大长度 |
| 属性 | 类型 | 说明 |
|---|---|---|
nullable | bool | 是否可空 |
required | bool | 是否必填 |
is_unique | bool | 是否唯一 |
db_index | bool | 是否有索引 |
default | any | 默认值 |
| 属性 | 类型 | 说明 |
|---|---|---|
is_image | bool | 图片字段 |
is_rich_text | bool | 富文本字段 |
| 属性 | 类型 | 说明 |
|---|---|---|
in_form | bool | 出现在表单中 |
in_list | bool | 出现在列表中 |
editable | bool | 可编辑 |
filterable | bool | 作为查询条件 |
filter_type | str | 筛选类型(精确匹配/模糊查询) |
searchable | bool | 可搜索 |
| 属性 | 类型 | 说明 |
|---|---|---|
choices | list | [{value: any, label: str}, ...] |
choices_name | str | 选项常量名 |
min_value | int | 最小值 |
max_value | int | 最大值 |
修改 public/templates/models.py.tpl:
{% 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 %}修改 public/templates/services.py.tpl,在添加方法中添加自定义校验:
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 }}名称已存在")
# ... 创建记录 ...修改 public/templates/ui/columns.ts.tpl:
{% for f in list_fields %}
{
label: '{{ f.label }}',
prop: '{{ f.camel_name }}',
minWidth: {{ 80 + (f.max_length or 100) // 3 }}, {# 动态列宽 #}
},
{% endfor %}如需生成额外文件(如测试文件),按以下步骤操作:
在 public/templates/ 下新建 test.py.tpl:
# 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)在 generator_config.py 的 generate() 方法中添加:
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', # 新增
]如果需要输出到非默认目录,修改 generate() 方法中的路径逻辑。
{# 注释 #}
{# 变量输出 #}
{{ 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 语法,每个模板对应一个生成文件。模板变量包括模块名、表名、字段列表等,字段属性包含名称、类型、注释、是否可搜索等。可通过修改模板自定义生成代码的风格和结构。