# 第四章 架构设计 - 分层架构详解 ## 4.1 分层架构概述 项目采用经典的五层架构设计,各层职责明确,依赖关系清晰: ``` +------------------+ | View Layer | <-- 视图层:接收请求,返回响应 +------------------+ | v +------------------+ | Service Layer | <-- 服务层:业务逻辑处理 +------------------+ | v +------------------+ | Form Layer | <-- 表单层:数据验证 +------------------+ | v +------------------+ | Model Layer | <-- 模型层:数据库操作 +------------------+ | v +------------------+ | URL Layer | <-- 路由层:URL映射 +------------------+ ``` ## 4.2 模型层 (Model Layer) ### 4.2.1 BaseModel 抽象基类 所有业务模型继承自 `BaseModel`(`application/models.py`),自动获得 6 个公共字段: ```python class BaseModel(models.Model): """基础模型抽象类""" # 主键ID字段 id = models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name='主键ID', db_comment='主键ID' ) # 创建人字段 create_user = models.CharField( null=True, max_length=50, default=None, verbose_name='创建人', db_comment='创建人' ) # 创建时间字段 create_time = models.DateTimeField( null=True, auto_now_add=True, verbose_name="创建时间", db_comment='创建时间' ) # 更新人字段 update_user = models.CharField( null=True, max_length=50, default=None, verbose_name='更新人', db_comment='更新人' ) # 更新时间字段 update_time = models.DateTimeField( null=True, auto_now=True, verbose_name="更新时间", db_comment='更新时间' ) # 逻辑删除标识 is_delete = models.BooleanField( default=0, db_default=0, verbose_name="逻辑删除", db_comment='逻辑删除:0-正常 1-已删除' ) class Meta: abstract = True # 抽象模型,不创建数据库表 ``` ### 4.2.2 业务模型示例 以案例模型为例(`application/example/models.py`): ```python 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='案例状态:1-正常 2-禁用' ) sort = models.IntegerField( null=False, verbose_name="排序", db_comment='排序' ) class Meta: db_table = get_table_name('example') # 自动生成表名 db_table_comment = "案例表" ordering = ("sort",) ``` ### 4.2.3 字段顺序重排 通过 `class_prepared` 信号,自动将公共字段移到业务字段之后: ```python BASE_FIELD_NAMES = ['id', 'create_user', 'create_time', 'update_user', 'update_time', 'is_delete'] def _reorder_fields(sender, **kwargs): """信号处理函数:重排模型字段顺序""" if not hasattr(sender, '_meta') or sender._meta.abstract: return base_fields = [] business_fields = [] for field in sender._meta.local_fields: if field.name in BASE_FIELD_NAMES: base_fields.append(field) else: business_fields.append(field) # 重新排列:业务字段在前,公共字段在后 sender._meta.local_fields = business_fields + base_fields class_prepared.connect(_reorder_fields) ``` ## 4.3 表单层 (Form Layer) ### 4.3.1 ModelForm 验证 表单层使用 Django 的 `ModelForm` 进行数据验证(`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个字符', } ) 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': '案例状态不能为空', } ) sort = forms.IntegerField( required=True, error_messages={'required': '排序不能为空'} ) class Meta: model = models.Example fields = ['name', 'avatar', 'type', 'status', 'sort'] ``` ### 4.3.2 验证错误处理 ```python # 在Service层使用表单验证 form = ExampleForm(data) if not form.is_valid(): # 获取第一个错误信息 return R.failed(msg=regular.get_err(form)) ``` ## 4.4 服务层 (Service Layer) ### 4.4.1 服务函数命名规范 服务层函数遵循统一的命名规范: | 函数类型 | 命名格式 | 示例 | |----------|----------|------| | 分页查询 | `get__page` | `get_example_page` | | 列表查询 | `get__list` | `get_example_list` | | 详情查询 | `get__detail` | `get_example_detail` | | 添加 | `add_` | `add_example` | | 更新 | `update_` | `update_example` | | 删除 | `delete_s` | `delete_examples` | | 状态更新 | `update__status` | `update_example_status` | ### 4.4.2 分页查询实现 ```python 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) page_list = paginator.page(page_no) # 构建并返回分页数据 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="查询失败,请稍后重试") ``` ### 4.4.3 添加操作实现 ```python def add_example(request): """添加案例""" data, error = parse_request_body(request) if error: return R.failed(msg=error) form = 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="添加失败,请稍后重试") ``` ### 4.4.4 删除操作实现(软删除) ```python 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()] # 批量更新删除标识(逻辑删除) 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格式错误") ``` ## 4.5 视图层 (View Layer) ### 4.5.1 视图类结构 视图层使用 Django 的类视图,结合装饰器和混入类实现认证和权限控制: ```python from django.utils.decorators import method_decorator from django.views import View from middleware.login_middleware import check_login from middleware.permission_middleware import PermissionRequired @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): result = services.get_example_page(request) return result ``` ### 4.5.2 视图类职责 | 职责 | 说明 | |------|------| | 请求接收 | 接收 HTTP 请求,提取参数 | | 认证检查 | 通过 `@check_login` 装饰器验证登录状态 | | 权限检查 | 通过 `PermissionRequired` 混入类验证操作权限 | | 参数校验 | 简单的参数格式校验(如 ID 有效性) | | 服务调用 | 调用 Service 层函数处理业务逻辑 | | 响应返回 | 返回 Service 层返回的响应结果 | ## 4.6 路由层 (URL Layer) ### 4.6.1 模块路由定义 每个模块在 `urls.py` 中定义自己的路由: ```python # application/example/urls.py 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()), ] ``` ### 4.6.2 主路由注册 所有模块路由在主路由中注册(`application/urls.py`): ```python from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('application.login.urls')), path('index/', include('application.index.urls')), path('example/', include('application.example.urls')), # ... 其他模块 ] ``` ## 4.7 数据流向 ### 4.7.1 请求数据流 ``` HTTP Request | v View.get/post/put/delete | v Service函数 | v parse_request_body(request) --> 解析JSON请求体 | v Form验证 --> 数据校验 | v Model操作 --> 数据库读写 | v 构建返回数据字典 | v R.ok()/R.failed() --> 构造响应 | v JsonResponse --> HTTP Response ``` ### 4.7.2 响应数据格式转换 ```python # Model对象 -> 字典 record = { 'id': item.id, 'name': item.name, 'avatar': get_file_url(item.avatar), 'createUser': item.create_user, # snake_case -> camelCase 'createTime': format_datetime(item.create_time), } # 字典 -> JSON return R.ok(data=record) # { # "code": 0, # "data": {"id": 1, "name": "...", "createUser": "admin"}, # "msg": "操作成功", # "ok": true # } ```