9.0 KiB
9.0 KiB
视图层(View)
视图层是模块开发的第四步,负责处理 HTTP 请求并调用 Service 层的业务逻辑。项目使用 Django 的类视图(Class-Based Views),每个视图类对应一个 API 端点。
文件位置
application/example/views.py
完整代码
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):
result = services.get_example_page(request)
return result
@method_decorator(check_login, name='get')
class ExampleListView(View):
"""案例列表获取视图(支持筛选,不分页)"""
def get(self, request):
result = services.get_example_list(request)
return R.ok(data=result)
@method_decorator(check_login, name="get")
class ExampleDetailView(PermissionRequired, View):
"""案例详情查询视图"""
permission_required = ("sys:example:detail",)
@operation_log(title="案例管理-查询记录详情", log_type=LogType.QUERY)
def get(self, request, id):
data = services.get_example_detail(id)
return R.ok(data=data)
@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("演示环境,暂无操作权限")
result = services.add_example(request)
return result
@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("演示环境,暂无操作权限")
result = services.update_example(request)
return result
@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("演示环境,暂无操作权限")
result = services.delete_examples(id)
return result
@method_decorator(check_login, name="put")
class ExampleStatusView(PermissionRequired, View):
"""设置案例状态视图"""
permission_required = ('sys:example:status',)
def put(self, request):
if DJANGO_DEMO:
return R.failed("演示环境,暂无操作权限")
result = services.update_example_status(request)
return result
@method_decorator(check_login, name='get')
class ExampleDataView(View):
"""案例列表获取视图"""
def get(self, request):
result = services.get_example_data()
return R.ok(data=result)
代码解析
视图类继承
@method_decorator(check_login, name="get")
class ExamplePageView(PermissionRequired, View):
| 基类/装饰器 | 来源 | 提供能力 |
|---|---|---|
View |
Django 内置 | 类视图基类,提供 get/post/put/delete 方法分发 |
PermissionRequired |
middleware/permission_middleware.py |
权限控制混入类 |
@method_decorator(check_login, name="get") |
middleware/login_middleware.py |
JWT 登录认证 |
三层防护机制
请求 → check_login(登录校验) → PermissionRequired(权限校验) → operation_log(操作日志) → 业务逻辑
1. 登录校验(check_login)
@method_decorator(check_login, name="get")
check_login 装饰器从请求头 Authorization: Bearer <token> 中提取 JWT token,验证其有效性。验证失败返回 401 Unauthorized。
def check_login(func):
def wrapper(request, *args, **kwargs):
ignoreURL = ['/login', '/captcha']
if request.path not in ignoreURL:
access_token = request.headers['Authorization']
access_token = access_token.replace('Bearer ', "")
result = parse_payload(access_token)
code = result['code']
if code != 0:
return R.failed(code=401, msg=result['msg'])
return func(request, *args, **kwargs)
return wrapper
2. 权限校验(PermissionRequired)
class ExamplePageView(PermissionRequired, View):
permission_required = ("sys:example:page",)
PermissionRequired 混入类重写了 has_permission() 方法,检查当前用户是否拥有所需的权限节点。用户 ID 为 1 的超级管理员自动放行。
class PermissionRequired(PermissionRequiredMixin):
def has_permission(self):
permissions = self.get_permission_required()
user_id = get_user_id(self.request)
# 超级管理员自动放行
if user_id and user_id != 1:
from application.menu import services
permission_list = services.get_user_permissions(user_id)
for permission in permissions:
if permission not in permission_list:
return False
return True
def handle_no_permission(self):
return R.failed("暂无操作权限", 401)
3. 操作日志(operation_log)
@operation_log(title="案例管理-查询分页列表", log_type=LogType.QUERY)
def get(self, request):
...
@operation_log 装饰器自动记录操作日志,包括操作标题、操作类型、请求参数、响应结果、耗时等信息。
| 参数 | 说明 |
|---|---|
title |
操作标题,如"案例管理-添加记录" |
log_type |
操作类型,参考 LogType 常量 |
source |
操作来源,0=后台系统 |
操作类型常量
class LogType:
OTHER = 0 # 其他操作
QUERY = 1 # 查询操作
ADD = 2 # 新增操作
UPDATE = 3 # 修改操作
SAVE = 4 # 保存操作
DELETE = 5 # 删除操作
BATCH_DELETE = 6 # 批量删除
STATUS = 7 # 设置状态
RESET_PWD = 8 # 重置密码
IMPORT = 9 # 导入操作
EXPORT = 10 # 导出操作
UPLOAD = 11 # 上传操作
演示环境检查
if DJANGO_DEMO:
return R.failed("演示环境,暂无操作权限")
写操作(add、update、delete、status)需要检查 DJANGO_DEMO 配置。当 .env 中设置 DJANGO_DEMO=True 时,所有写操作返回失败提示。
视图类分类
| 视图类 | HTTP 方法 | 权限 | 说明 |
|---|---|---|---|
ExamplePageView |
GET | sys:example:page |
分页查询 |
ExampleListView |
GET | 无(仅登录) | 列表查询(不分页) |
ExampleDetailView |
GET | sys:example:detail |
详情查询 |
ExampleAddView |
POST | sys:example:add |
添加记录 |
ExampleUpdateView |
PUT | sys:example:update |
更新记录 |
ExampleDeleteView |
DELETE | sys:example:delete |
删除记录 |
ExampleStatusView |
PUT | sys:example:status |
状态更新 |
ExampleDataView |
GET | 无(仅登录) | 数据列表(下拉选择) |
权限节点格式
sys:<module>:<action>
| 部分 | 说明 | 示例 |
|---|---|---|
sys |
固定前缀 | sys |
<module> |
模块名称 | example |
<action> |
操作类型 | page、list、detail、add、update、delete、status |
开发要点
- 每个视图类只处理一个 HTTP 方法:单一职责原则
- 使用
@method_decorator(check_login, name="方法名")进行登录校验:确保用户已登录 - 需要权限控制的视图继承
PermissionRequired:并设置permission_required - 写操作必须检查
DJANGO_DEMO:演示环境禁止写操作 - 使用
@operation_log记录操作日志:便于审计和追踪 - 视图层只做请求分发:业务逻辑全部委托给 Service 层
- 直接返回 Service 层的结果:不要在视图层处理业务逻辑
总结
视图层使用 Django 类视图,组合三层防护机制:登录校验(check_login)、权限控制(PermissionRequired)、操作日志(operation_log)。每个视图类只处理一个 HTTP 方法,写操作需要检查 DJANGO_DEMO 配置。视图层只做请求分发,业务逻辑全部委托给 Service 层。