Skip to content

视图层(View)

视图层是模块开发的第四步,负责处理 HTTP 请求并调用 Service 层的业务逻辑。项目使用 Django 的类视图(Class-Based Views),每个视图类对应一个 API 端点。

文件位置

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):
    """
    案例分页数据查询视图

    处理GET请求,返回案例列表的分页数据。
    支持按案例名称、案例类型、案例状态等条件筛选。

    URL: /example/page
    请求方法: GET
    权限要求:sys:example:page
    """

    # 方法权限标识
    permission_required = ("sys:example:page",)

    @operation_log(
        title="案例管理-查询分页列表",
        log_type=LogType.QUERY
    )
    def get(self, request):
        """
        处理GET请求,返回案例分页数据

        Args:
            request: HttpRequest对象,包含分页参数和筛选条件
                - pageNo: 当前页码
                - pageSize: 每页记录数
                - name: 案例名称(可选,模糊查询)
                - type: 案例类型(可选,精确匹配)
                - status: 案例状态(可选,精确匹配)

        Returns:
            JsonResponse: 包含分页数据的JSON响应
        """
        result = services.get_example_page(request)
        return result


# =============================================================
# 列表查询视图(不分页)
# =============================================================

@method_decorator(check_login, name='get')
class ExampleListView(View):
    """
    案例列表获取视图(支持筛选,不分页)

    处理GET请求,返回所有案例的列表数据。
    支持按案例名称、案例类型、案例状态等条件筛选。

    URL: /example/list
    请求方法: GET
    权限要求:需要登录
    """

    def get(self, request):
        """
        处理GET请求,返回案例列表

        Args:
            request: HttpRequest对象

        Returns:
            JsonResponse: 包含案例列表的JSON响应
        """
        result = services.get_example_list(request)
        return R.ok(data=result)


# =============================================================
# 详情查询视图
# =============================================================

@method_decorator(check_login, name="get")
class ExampleDetailView(PermissionRequired, View):
    """
    案例详情查询视图

    处理GET请求,根据案例ID返回案例详细信息。

    URL: /example/detail/<int:id>
    请求方法: GET
    权限要求:sys:example:detail
    """

    # 方法权限标识
    permission_required = ("sys:example:detail",)

    @operation_log(
        title="案例管理-查询记录详情",
        log_type=LogType.QUERY
    )
    def get(self, request, id):
        """
        处理GET请求,返回案例详情

        Args:
            request: HttpRequest对象
            id: 案例ID(URL参数)

        Returns:
            JsonResponse: 包含案例详情的JSON响应
        """
        data = services.get_example_detail(id)
        return R.ok(data=data)


# =============================================================
# 添加视图
# =============================================================

@method_decorator(check_login, name="post")
class ExampleAddView(PermissionRequired, View):
    """
    添加案例视图

    处理POST请求,创建新的案例记录。
    请求体需包含案例信息(name、avatar、type、status、sort等)。

    URL: /example/add
    请求方法: POST
    权限要求:sys:example:add
    """

    # 方法权限标识
    permission_required = ("sys:example:add",)

    @operation_log(
        title="案例管理-添加记录",
        log_type=LogType.ADD
    )
    def post(self, request):
        """
        处理POST请求,添加案例

        Args:
            request: HttpRequest对象,请求体包含案例信息

        Returns:
            JsonResponse: 操作结果的JSON响应
        """
        # 演示模式检查
        if DJANGO_DEMO:
            return R.failed("演示环境,暂无操作权限")
        result = services.add_example(request)
        return result


# =============================================================
# 更新视图
# =============================================================

@method_decorator(check_login, name="put")
class ExampleUpdateView(PermissionRequired, View):
    """
    更新案例视图

    处理PUT请求,更新现有案例信息。
    请求体需包含案例ID和更新内容。

    URL: /example/update
    请求方法: PUT
    权限要求:sys:example:update
    """

    # 方法权限标识
    permission_required = ('sys:example:update',)

    @operation_log(
        title="案例管理-更新记录",
        log_type=LogType.UPDATE
    )
    def put(self, request):
        """
        处理PUT请求,更新案例

        Args:
            request: HttpRequest对象,请求体包含更新信息

        Returns:
            JsonResponse: 操作结果的JSON响应
        """
        # 演示模式检查
        if DJANGO_DEMO:
            return R.failed("演示环境,暂无操作权限")
        result = services.update_example(request)
        return result


# =============================================================
# 删除视图
# =============================================================

@method_decorator(check_login, name="delete")
class ExampleDeleteView(PermissionRequired, View):
    """
    删除案例视图

    处理DELETE请求,删除指定案例(逻辑删除)。
    支持批量删除,多个ID用逗号分隔。

    URL: /example/delete/<str:id>
    请求方法: DELETE
    权限要求:sys:example:delete
    """

    # 方法权限标识
    permission_required = ('sys:example:delete',)

    @operation_log(
        title="案例管理-删除记录",
        log_type=LogType.DELETE
    )
    def delete(self, request, id):
        """
        处理DELETE请求,删除案例

        Args:
            request: HttpRequest对象
            id: 案例ID字符串,支持逗号分隔的多个ID(如 "1,2,3")

        Returns:
            JsonResponse: 操作结果的JSON响应
        """
        # 演示模式检查
        if DJANGO_DEMO:
            return R.failed("演示环境,暂无操作权限")
        result = services.delete_examples(id)
        return result


# =============================================================
# 状态更新视图
# =============================================================

@method_decorator(check_login, name="put")
class ExampleStatusView(PermissionRequired, View):
    """
    设置案例状态视图

    处理PUT请求,更新案例的启用/禁用状态。

    URL: /example/status
    请求方法: PUT
    权限要求:sys:example:status
    """

    # 方法权限标识
    permission_required = ('sys:example:status',)

    def put(self, request):
        """
        处理PUT请求,更新案例状态

        Args:
            request: HttpRequest对象,请求体包含案例ID和新状态

        Returns:
            JsonResponse: 操作结果的JSON响应
        """
        # 演示模式检查
        if DJANGO_DEMO:
            return R.failed("演示环境,暂无操作权限")
        result = services.update_example_status(request)
        return result


# =============================================================
# 数据列表视图(下拉选择用)
# =============================================================

@method_decorator(check_login, name='get')
class ExampleDataView(View):
    """
    案例列表获取视图

    处理GET请求,返回所有启用案例的列表数据。
    用于下拉选择等前端组件。

    URL: /example/data
    请求方法: GET
    权限要求:需要登录
    """

    def get(self, request):
        """
        处理GET请求,返回案例数据列表

        Args:
            request: HttpRequest对象

        Returns:
            JsonResponse: 包含案例列表的JSON响应
        """
        result = services.get_example_data()
        return R.ok(data=result)

代码解析

视图类继承

python
@method_decorator(check_login, name="get")
class ExamplePageView(PermissionRequired, View):
基类/装饰器来源提供能力
ViewDjango 内置类视图基类,提供 get/post/put/delete 方法分发
PermissionRequiredmiddleware/permission_middleware.py权限控制混入类
@method_decorator(check_login, name="get")middleware/login_middleware.pyJWT 登录认证

三层防护机制

请求 → check_login(登录校验) → PermissionRequired(权限校验) → operation_log(操作日志) → 业务逻辑

1. 登录校验(check_login)

python
@method_decorator(check_login, name="get")

check_login 装饰器从请求头 Authorization: Bearer <token> 中提取 JWT token,验证其有效性。验证失败返回 401 Unauthorized

python
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)

python
class ExamplePageView(PermissionRequired, View):
    permission_required = ("sys:example:page",)

PermissionRequired 混入类重写了 has_permission() 方法,检查当前用户是否拥有所需的权限节点。用户 ID 为 1 的超级管理员自动放行。

python
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)

python
@operation_log(title="案例管理-查询分页列表", log_type=LogType.QUERY)
def get(self, request):
    ...

@operation_log 装饰器自动记录操作日志,包括操作标题、操作类型、请求参数、响应结果、耗时等信息。

参数说明
title操作标题,如"案例管理-添加记录"
log_type操作类型,参考 LogType 常量
source操作来源,0=后台系统

操作类型常量

python
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      # 上传操作

演示环境检查

python
if DJANGO_DEMO:
    return R.failed("演示环境,暂无操作权限")

写操作(add、update、delete、status)需要检查 DJANGO_DEMO 配置。当 .env 中设置 DJANGO_DEMO=True 时,所有写操作返回失败提示。

视图类分类

视图类HTTP 方法权限说明
ExamplePageViewGETsys:example:page分页查询
ExampleListViewGET无(仅登录)列表查询(不分页)
ExampleDetailViewGETsys:example:detail详情查询
ExampleAddViewPOSTsys:example:add添加记录
ExampleUpdateViewPUTsys:example:update更新记录
ExampleDeleteViewDELETEsys:example:delete删除记录
ExampleStatusViewPUTsys:example:status状态更新
ExampleDataViewGET无(仅登录)数据列表(下拉选择)

权限节点格式

sys:<module>:<action>
部分说明示例
sys固定前缀sys
<module>模块名称example
<action>操作类型pagelistdetailaddupdatedeletestatus

开发要点

  1. 每个视图类只处理一个 HTTP 方法:单一职责原则
  2. 使用 @method_decorator(check_login, name="方法名") 进行登录校验:确保用户已登录
  3. 需要权限控制的视图继承 PermissionRequired:并设置 permission_required
  4. 写操作必须检查 DJANGO_DEMO:演示环境禁止写操作
  5. 使用 @operation_log 记录操作日志:便于审计和追踪
  6. 视图层只做请求分发:业务逻辑全部委托给 Service 层
  7. 直接返回 Service 层的结果:不要在视图层处理业务逻辑

总结

视图层使用 Django 类视图,组合三层防护机制:登录校验(check_login)、权限控制(PermissionRequired)、操作日志(operation_log)。每个视图类只处理一个 HTTP 方法,写操作需要检查 DJANGO_DEMO 配置。视图层只做请求分发,业务逻辑全部委托给 Service 层。

小蚂蚁云团队 · 提供技术支持