Files
djangoadmin-wiki/DjangoAdmin_FastAPI_EleVue/zh/volume5/templates.md
T
2026-09-13 22:47:31 +08:00

297 lines
8.2 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 语法说明,包括模板变量、字段属性和自定义模板的开发方法。
:::
# 自定义模板
模板文件位于 `src/modules/generator/templates/`,使用 Jinja2 语法。修改模板后重新生成即可生效。
## 模板目录结构
```
templates/
├── __init__.py.tpl # 模块初始化
├── models.py.tpl # ORM 模型
├── schemas.py.tpl # Pydantic 表单
├── repository.py.tpl # 数据访问层
├── service.py.tpl # 业务逻辑层
├── endpoint.py.tpl # HTTP 端点
├── 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 # 树形详情弹窗
```
## ui/ vs ui2/ 切换逻辑
当表中存在 `parent_id` 或 `pid` 字段时,自动切换为 `ui2/` 树形模板:
```
字段列表中是否有 parent_id / pid?
├── 是 → 使用 ui2/ 模板(3 个组件 + 1 个 API)
└── 否 → 使用 ui/ 模板(5 个组件 + 1 个 API)
```
两者共用 `ui/api.ts.tpl` 生成 API 接口文件。
## 模板变量
### 基础变量
| 变量 | 类型 | 说明 | 示例 |
|:----|:----|:----|:----|
| `app_name` | str | 模块名 | `example` |
| `module_comment` | str | 中文名 | `案例` |
| `module_comment_py` | str | 转义后中文名 | `案例` |
| `model_class_name` | str | 类名 | `Example` |
| `permission_prefix` | str | 权限前缀 | `sys:example` |
| `display_field` | str | 显示字段 | `name` |
| `sort_field` | str | 排序字段 | `sort` |
### 功能标识
| 变量 | 类型 | 说明 |
|:----|:----|:----|
| `has_sort` | bool | 有排序字段 |
| `has_status` | bool | 有状态字段 |
| `has_status_route` | bool | 生成状态路由 |
| `has_image_field` | bool | 有图片字段 |
| `has_rich_text_field` | bool | 有富文本字段 |
| `serialize_maps` | dict | 枚举映射 `{field_name: dict_code}` |
### 字段列表
| 变量 | 类型 | 说明 |
|:----|:----|:----|
| `fields` | list | 全部字段 |
| `form_fields` | list | 表单字段(`in_form=True`) |
| `filter_fields` | list | 精确匹配字段 |
| `like_fields` | list | 模糊查询字段 |
### 前端专用变量
| 变量 | 类型 | 说明 |
|:----|:----|:----|
| `module_name` | str | 驼峰模块名 |
| `model_class_name_camel` | str | 驼峰类名(首字母小写) |
| `list_fields` | list | 列表展示字段 |
| `searchable_fields` | list | 可搜索字段 |
| `editable_fields` | list | 可编辑字段 |
| `is_tree_structure` | bool | 是否树形结构 |
| `parent_id_field` | str | 父级字段名 |
| `route_prefix` | str | 路由前缀 |
| `api_path` | str | API 路径 |
| `has_search_form` | bool | 显示搜索表单 |
| `show_selection` | bool | 显示复选框 |
| `action_column_width` | int | 操作列宽度 |
## 字段对象属性
`fields` 列表中每个字段对象包含以下属性:
### 基础属性
| 属性 | 类型 | 说明 |
|:----|:----|:----|
| `name` | str | 字段名(snake_case) |
| `camel_name` | str | 驼峰字段名 |
| `comment` | str | 字段注释 |
| `py_comment` | str | 转义后注释(可嵌入 Python 字符串) |
| `label` | str | 清洗后的注释(去掉选项说明) |
### 类型属性
| 属性 | 类型 | 说明 |
|:----|:----|:----|
| `db_type` | str | SQLAlchemy 类型 |
| `db_args` | str | 类型参数(如 `"100"`) |
| `form_type` | str | Pydantic 类型 |
| `type_display` | str | 中文类型名 |
| `max_length` | int | 最大长度 |
### 约束属性
| 属性 | 类型 | 说明 |
|:----|:----|:----|
| `nullable` | bool | 是否可空 |
| `required` | bool | 是否必填 |
| `is_unique` | bool | 是否唯一 |
| `default` | any | 默认值 |
| `default_repr` | str | 默认值 Python 表示 |
### 功能标识
| 属性 | 类型 | 说明 |
|:----|:----|:----|
| `is_image` | bool | 图片字段 |
| `is_rich_text` | bool | 富文本字段 |
| `is_status` | bool | 状态字段 |
| `is_sort` | bool | 排序字段 |
### 展示控制
| 属性 | 类型 | 说明 |
|:----|:----|:----|
| `in_form` | bool | 出现在表单中 |
| `in_list` | bool | 出现在列表中 |
| `editable` | bool | 可编辑 |
| `filterable` | bool | 作为查询条件 |
| `filter_type` | str | 筛选类型 |
| `searchable` | bool | 可搜索 |
### 选项属性
| 属性 | 类型 | 说明 |
|:----|:----|:----|
| `choices` | list | `[(value, label), ...]` |
| `dict_code` | str | 数据字典编码 |
| `min_value` | int | 最小值 |
| `max_value` | int | 最大值 |
### 前端专用
| 属性 | 类型 | 说明 |
|:----|:----|:----|
| `purpose` | str | 用途说明 |
| `type` | str | 配置字段类型名(CharField/IntegerField/...) |
| `choices[].value` | any | 选项值 |
| `choices[].label` | str | 选项文本 |
| `choices[].type` | str | 标签颜色(success/danger/warning/info) |
## 自定义模板示例
### 示例 1:为所有字段添加索引
修改 `templates/models.py.tpl`:
```jinja
{% if f.db_type == 'String' %}
{{ f.name }} = Column(String({{ f.db_args or 255 }}), nullable={{ 'True' if f.nullable else 'False' }}, index=True, comment="{{ f.comment }}")
{% endif %}
```
### 示例 2:自定义 Service 钩子
修改 `templates/service.py.tpl`,在 Service 类中添加钩子方法:
```jinja
class {{ model_class_name }}Service(BaseService[{{ model_class_name }}]):
# ... 差异点声明 ...
{% if has_status %}
def _before_delete(self, ids) -> Optional[str]:
"""删除前校验:检查是否有关联数据"""
# TODO: 添加自定义校验逻辑
return None
{% endif %}
```
### 示例 3:自定义前端表格列宽
修改 `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 步:创建模板文件
在 `templates/` 下新建 `test.py.tpl`:
```jinja
# tests/test_{{ app_name }}.py
import pytest
from modules.{{ app_name }}.service import {{ app_name }}_service
class Test{{ model_class_name }}:
def test_get_page(self, client):
response = client.get("/api/v1/{{ app_name }}/page")
assert response.status_code == 200
```
### 第 2 步:注册到 BACKEND_TEMPLATES
在 `code_generator.py` 中添加:
```python
BACKEND_TEMPLATES = [
'__init__.py.tpl',
'models.py.tpl',
'schemas.py.tpl',
'repository.py.tpl',
'service.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 }}_repo
{# 默认值 #}
{{ f.db_args or 255 }}
```
## 总结
模板使用 Jinja2 语法,每个模板对应一个生成文件。模板变量包括模块名、表名、字段列表等,字段属性包含名称、类型、注释、是否可搜索等。可通过修改模板自定义生成代码的风格和结构。