Become a sponsor

项目采用经典的五层架构设计,各层职责明确,依赖关系清晰:
+------------------+
| View Layer | <-- 视图层:接收请求,返回响应
+------------------+
|
v
+------------------+
| Service Layer | <-- 服务层:业务逻辑处理
+------------------+
|
v
+------------------+
| Form Layer | <-- 表单层:数据验证
+------------------+
|
v
+------------------+
| Model Layer | <-- 模型层:数据库操作
+------------------+
|
v
+------------------+
| URL Layer | <-- 路由层:URL映射
+------------------+所有业务模型继承自 BaseModel(application/models.py),自动获得 6 个公共字段:
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 # 抽象模型,不创建数据库表以案例模型为例(application/example/models.py):
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",)通过 class_prepared 信号,自动将公共字段移到业务字段之后:
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)表单层使用 Django 的 ModelForm 进行数据验证(application/example/forms.py):
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']# 在Service层使用表单验证
form = ExampleForm(data)
if not form.is_valid():
# 获取第一个错误信息
return R.failed(msg=regular.get_err(form))服务层函数遵循统一的命名规范:
| 函数类型 | 命名格式 | 示例 |
|---|---|---|
| 分页查询 | get_<module>_page | get_example_page |
| 列表查询 | get_<module>_list | get_example_list |
| 详情查询 | get_<module>_detail | get_example_detail |
| 添加 | add_<module> | add_example |
| 更新 | update_<module> | update_example |
| 删除 | delete_<module>s | delete_examples |
| 状态更新 | update_<module>_status | update_example_status |
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="查询失败,请稍后重试")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="添加失败,请稍后重试")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格式错误")视图层使用 Django 的类视图,结合装饰器和混入类实现认证和权限控制:
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| 职责 | 说明 |
|---|---|
| 请求接收 | 接收 HTTP 请求,提取参数 |
| 认证检查 | 通过 @check_login 装饰器验证登录状态 |
| 权限检查 | 通过 PermissionRequired 混入类验证操作权限 |
| 参数校验 | 简单的参数格式校验(如 ID 有效性) |
| 服务调用 | 调用 Service 层函数处理业务逻辑 |
| 响应返回 | 返回 Service 层返回的响应结果 |
每个模块在 urls.py 中定义自己的路由:
# 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/<int:id>', views.ExampleDetailView.as_view()),
path('add', views.ExampleAddView.as_view()),
path('update', views.ExampleUpdateView.as_view()),
path('delete/<str:id>', views.ExampleDeleteView.as_view()),
path('status', views.ExampleStatusView.as_view()),
]所有模块路由在主路由中注册(application/urls.py):
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')),
# ... 其他模块
]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# 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
# }