# 完整代码清单 本章汇总 Example 案例模块涉及的全部文件,便于开发时快速查阅和复制。 ## 后端文件清单 ### 1. 数据模型 `application/example/models.py` ```python from django.db import models from application.models import BaseModel from utils.common import get_table_name class Example(BaseModel): """案例模型类""" name = models.CharField(null=False, max_length=100, db_index=True, verbose_name="案例名称", db_comment='案例名称') avatar = models.CharField(null=True, blank=True, max_length=255, verbose_name="案例图片", db_comment='案例图片') TYPE_CHOICES = ((1, "类型1"), (2, "类型2"), (3, "类型3"), (4, "类型4"),) type = models.IntegerField(null=False, choices=TYPE_CHOICES, verbose_name="案例类型", db_comment='案例类型') STATUS_CHOICES = ((1, "正常"), (2, "禁用"),) status = models.IntegerField(null=False, choices=STATUS_CHOICES, verbose_name="案例状态", db_comment='案例状态') sort = models.IntegerField(null=False, verbose_name="排序", db_comment='排序') class Meta: db_table = get_table_name('example') db_table_comment = "案例表" verbose_name = "案例表" verbose_name_plural = verbose_name ordering = ("sort",) ``` ### 2. 表单验证 `application/example/forms.py` ```python from django import forms from application.example import models class ExampleForm(forms.ModelForm): """案例表单验证类""" name = forms.CharField(required=True, max_length=100, error_messages={ 'required': '案例名称不能为空', 'max_length': '案例名称长度不得超过100个字符'}) avatar = forms.CharField(required=False, max_length=255, error_messages={ 'max_length': '案例图片长度不得超过255个字符'}) type = forms.IntegerField(required=True, min_value=1, max_value=4, error_messages={ 'required': '案例类型不能为空', 'min_value': '案例类型值不能小于1', 'max_value': '案例类型值不能大于4'}) status = forms.IntegerField(required=True, min_value=1, max_value=2, error_messages={ 'required': '案例状态不能为空', 'min_value': '案例状态值不能小于1', 'max_value': '案例状态值不能大于2'}) sort = forms.IntegerField(required=True, error_messages={'required': '排序不能为空'}) class Meta: model = models.Example fields = ['name', 'avatar', 'type', 'status', 'sort'] ``` ### 3. 业务逻辑层 `application/example/services.py` ```python import json import logging from django.core.paginator import Paginator, PageNotAnInteger, InvalidPage, EmptyPage from application.example import forms from application.example.models import Example from config.env import DJANGO_FILE_URL from constant.constants import PAGE_SIZE from utils import R, regular from utils.common import get_file_url, format_datetime, parse_request_body, save_file from utils.security import get_username def get_example_page(request): """查询案例分页数据""" try: page_no = int(request.GET.get('pageNo', 1)) page_size = int(request.GET.get('pageSize', PAGE_SIZE)) query = Example.objects.filter(is_delete=False) query = _apply_filters(query, request) query = query.order_by("sort") paginator = Paginator(query, page_size) try: page_list = paginator.page(page_no) except (PageNotAnInteger, InvalidPage, EmptyPage): page_list = paginator.page(1) page_no = 1 page_data = _build_page_data(page_list, paginator, page_no, page_size) return R.ok(data=page_data) except Exception as e: logging.error(f"查询案例分页数据异常: {str(e)}") return R.failed(msg="查询失败,请稍后重试") def add_example(request): """添加案例""" data, error = parse_request_body(request) if error: return R.failed(msg=error) form = forms.ExampleForm(data) if not form.is_valid(): return R.failed(msg=regular.get_err(form)) try: cleaned_data = form.cleaned_data avatar = cleaned_data.get('avatar') if avatar: avatar = save_file(avatar, "example") Example.objects.create( name=cleaned_data.get('name'), avatar=avatar, type=cleaned_data.get('type'), status=cleaned_data.get('status'), sort=cleaned_data.get('sort'), create_user=get_username(request), update_user=get_username(request)) return R.ok(msg="创建成功") except Exception as e: logging.error(f"添加案例异常: {str(e)}") return R.failed(msg="添加失败,请稍后重试") def update_example(request): """更新案例""" data, error = parse_request_body(request) if error: return R.failed(msg=error) instance_id = data.get('id') if not instance_id or not str(instance_id).isdigit() or int(instance_id) <= 0: return R.failed("案例ID无效") instance_id = int(instance_id) form = forms.ExampleForm(data) if not form.is_valid(): return R.failed(msg=regular.get_err(form)) try: instance = Example.objects.filter(id=instance_id, is_delete=False).first() if not instance: return R.failed("案例不存在") cleaned_data = form.cleaned_data avatar = cleaned_data.get('avatar') if avatar and avatar != instance.avatar: avatar = save_file(avatar, "example") else: avatar = instance.avatar instance.name = cleaned_data.get('name') instance.avatar = avatar instance.type = cleaned_data.get('type') instance.status = cleaned_data.get('status') instance.sort = cleaned_data.get('sort') instance.update_user = get_username(request) instance.save() return R.ok(msg="更新成功") except Exception as e: logging.error(f"更新案例异常,ID: {instance_id}, 错误: {str(e)}") return R.failed(msg="更新失败,请稍后重试") def delete_examples(instance_ids): """删除案例(批量删除)""" if not instance_ids: return R.failed("记录ID不存在") try: id_list = [int(id_str.strip()) for id_str in instance_ids.split(',') if id_str.strip()] if not id_list: return R.failed("无效的记录ID") updated_count = Example.objects.filter(id__in=id_list, is_delete=False).update(is_delete=True) return R.ok(msg=f"本次共删除{updated_count}条数据") except ValueError: return R.failed("记录ID格式错误") def update_example_status(request): """更新案例状态""" data, error = parse_request_body(request) if error: return R.failed(msg=error) instance_id = data.get('id') if not instance_id or not str(instance_id).isdigit() or int(instance_id) <= 0: return R.failed("案例ID无效") instance_id = int(instance_id) status = data.get('status') if status is None: return R.failed("状态值不能为空") try: status = int(status) if status not in [1, 2]: return R.failed("状态值无效") except ValueError: return R.failed("状态值格式错误") try: instance = Example.objects.filter(id=instance_id, is_delete=False).first() if not instance: return R.failed("案例不存在") instance.status = status instance.update_user = get_username(request) instance.save() return R.ok(msg="状态更新成功") except Exception as e: logging.error(f"更新案例状态异常,ID: {instance_id}, 错误: {str(e)}") return R.failed(msg="状态更新失败,请稍后重试") ``` ### 4. 视图层 `application/example/views.py` ```python from django.utils.decorators import method_decorator from django.views import View from application.example import services from config.env import DJANGO_DEMO from middleware.login_middleware import check_login from middleware.permission_middleware import PermissionRequired from utils import R from application.operation_log.constants import LogType from application.operation_log.decorators import operation_log @method_decorator(check_login, name="get") class ExamplePageView(PermissionRequired, View): """案例分页数据查询视图""" permission_required = ("sys:example:page",) @operation_log(title="案例管理-查询分页列表", log_type=LogType.QUERY) def get(self, request): return services.get_example_page(request) @method_decorator(check_login, name="post") class ExampleAddView(PermissionRequired, View): """添加案例视图""" permission_required = ("sys:example:add",) @operation_log(title="案例管理-添加记录", log_type=LogType.ADD) def post(self, request): if DJANGO_DEMO: return R.failed("演示环境,暂无操作权限") return services.add_example(request) @method_decorator(check_login, name="put") class ExampleUpdateView(PermissionRequired, View): """更新案例视图""" permission_required = ('sys:example:update',) @operation_log(title="案例管理-更新记录", log_type=LogType.UPDATE) def put(self, request): if DJANGO_DEMO: return R.failed("演示环境,暂无操作权限") return services.update_example(request) @method_decorator(check_login, name="delete") class ExampleDeleteView(PermissionRequired, View): """删除案例视图""" permission_required = ('sys:example:delete',) @operation_log(title="案例管理-删除记录", log_type=LogType.DELETE) def delete(self, request, id): if DJANGO_DEMO: return R.failed("演示环境,暂无操作权限") return services.delete_examples(id) ``` ### 5. 路由配置 `application/example/urls.py` ```python from django.urls import path from application.example import views urlpatterns = [ path('page', views.ExamplePageView.as_view()), path('list', views.ExampleListView.as_view()), path('detail/', views.ExampleDetailView.as_view()), path('add', views.ExampleAddView.as_view()), path('update', views.ExampleUpdateView.as_view()), path('delete/', views.ExampleDeleteView.as_view()), path('status', views.ExampleStatusView.as_view()), path('list', views.ExampleDataView.as_view()), ] ``` ### 6. 应用配置 `application/example/apps.py` ```python from django.apps import AppConfig class ExampleConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'application.example' ``` ### 7. 主路由注册(追加到 `application/urls.py`) ```python # 案例模块路由 path('example/', include('application.example.urls')), ``` ### 8. settings.py 注册应用 在 `INSTALLED_APPS` 中添加: ```python INSTALLED_APPS = [ ... 'application.example', ] ``` ## 前端文件清单 ### 9. API 请求 `ui/src/api/tool/example.ts` ```typescript import { http } from '@/utils/http/axios'; export function getExamplePage(params?) { return http.request({ url: '/example/page', method: 'GET', params }); } export function getExampleList(params?) { return http.request({ url: '/example/list', method: 'GET', params }); } export function getExampleDetail(id) { return http.request({ url: '/example/detail/' + id, method: 'get' }); } export function exampleAdd(data: any) { return http.request({ url: '/example/add', method: 'POST', data }); } export function exampleUpdate(data: any) { return http.request({ url: '/example/update', method: 'PUT', data }); } export function exampleDelete(id) { return http.request({ url: '/example/delete/' + id, method: 'DELETE' }); } ``` ### 10. 页面视图(5 个文件) | 文件 | 说明 | |:----|:----| | `ui/src/views/tool/example/index.vue` | 主页面:搜索 + 表格 + 操作 | | `ui/src/views/tool/example/edit.vue` | 编辑弹窗:新增/编辑表单 | | `ui/src/views/tool/example/detail.vue` | 详情弹窗:查看记录详情 | | `ui/src/views/tool/example/columns.ts` | 表格列定义 | | `ui/src/views/tool/example/querySchemas.ts` | 搜索表单 Schema | 参考 [前端页面视图](/zh/volume2/fe-view) 中的完整代码。 ## 文件总览 ``` 后端(application/example/) ├── models.py # 数据模型 ├── forms.py # 表单验证 ├── services.py # 业务逻辑层 ├── views.py # 视图层 ├── urls.py # 路由配置 ├── apps.py # 应用配置 ├── admin.py # Django Admin 注册 └── migrations/ # 数据库迁移文件 前端(ui/src/) ├── api/tool/ │ └── example.ts # API 请求封装 └── views/tool/example/ ├── index.vue # 主页面 ├── edit.vue # 编辑弹窗 ├── detail.vue # 详情弹窗 ├── columns.ts # 表格列定义 └── querySchemas.ts # 搜索表单 Schema 注册文件 ├── application/urls.py # 主路由注册 ├── application/settings.py # INSTALLED_APPS 注册 └── 数据库菜单表 # 菜单和权限节点 ``` ## 开发检查清单 完成后端开发后,按顺序检查: - [ ] `models.py` 已定义模型,表名使用 `get_table_name()` 加前缀 - [ ] `forms.py` 已定义表单类,中文错误提示 - [ ] `services.py` 已实现所有 CRUD 函数 - [ ] `views.py` 已定义视图类 + 权限装饰器 + 操作日志 - [ ] `urls.py` 已配置路由 - [ ] `application/urls.py` 已注册模块路由 - [ ] `application/settings.py` 已注册应用 - [ ] 菜单管理中已添加权限节点 完成前端开发后,按顺序检查: - [ ] `api/tool/example.ts` 已封装所有接口 - [ ] `views/tool/example/index.vue` 主页面已实现 - [ ] `views/tool/example/edit.vue` 编辑弹窗已实现 - [ ] `views/tool/example/detail.vue` 详情弹窗已实现 - [ ] `views/tool/example/columns.ts` 列定义已配置 - [ ] `views/tool/example/querySchemas.ts` 搜索 Schema 已配置 - [ ] 后端菜单已配置组件路径 - [ ] 页面可正常访问和操作 ## 总结 完整模块涉及后端 6 个文件(models/forms/services/views/urls/apps)+ 路由注册 + 应用注册 + 权限配置,前端 5 个文件(index.vue/edit.vue/detail.vue/columns.ts/querySchemas.ts)+ API 文件。代码生成器可根据数据库表自动生成全套代码。