Files
djangoadmin-wiki/DjangoAdmin_Django_EleVue/zh/volume5/templates.md
T
2026-09-13 17:33:13 +08:00

296 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
:::tip 本章概要
代码生成器模板的 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_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 | 最大值 |
## 自定义模板示例
### 示例 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.py` 的 `generate()` 方法中添加:
```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 语法,每个模板对应一个生成文件。模板变量包括模块名、表名、字段列表等,字段属性包含名称、类型、注释、是否可搜索等。可通过修改模板自定义生成代码的风格和结构。