Files
djangoadmin-wiki/DjangoAdmin_Flask_NaiveVue/zh/volume7/router.md
T
2026-09-12 23:12:15 +08:00

6.7 KiB

Router层规范

概述

Router 层是 HTTP 接口层,负责定义路由、权限装饰器和请求参数绑定。每个业务模块对应一个 router 文件,所有业务逻辑委托给 Service 层处理。

:::tip 设计原则

  • Router 层不含业务逻辑,仅做路由定义、权限校验和参数绑定
  • 装饰器顺序固定为:路由 → 权限
  • Service 函数使用延迟导入,避免循环引用 :::

完整示例

以岗位模块为例,src/modules/system/position/router.py 完整内容:

from flask import Blueprint, request

from src.core.permission import check_permission
from src.core.response import R
from src.common.utils.request import parse_request_body, parse_id_list

# ============================================================
# 创建 Blueprint 实例
# ============================================================
position_blue = Blueprint('position', __name__, url_prefix='/position')


# ============================================================
# 查询分页数据
# ============================================================
@position_blue.route('/page', methods=['GET'])
@check_permission('sys:position:page')
def page():
    """获取岗位分页列表"""
    from src.modules.system.position.service import get_position_page
    return get_position_page()


# ============================================================
# 查询岗位详情
# ============================================================
@position_blue.route('/detail/<int:id>', methods=['GET'])
@check_permission('sys:position:detail')
def detail(id):
    """根据岗位ID查询详细信息"""
    from src.modules.system.position.service import get_position_detail
    return R.ok(data=get_position_detail(id))


# ============================================================
# 获取岗位列表
# ============================================================
@position_blue.route('/list', methods=['GET'])
@check_permission('sys:position:list')
def get_position_list():
    """获取所有岗位列表(无分页,用于下拉选择)"""
    from src.modules.system.position.service import get_position_list
    return R.ok(data=get_position_list())


# ============================================================
# 添加岗位
# ============================================================
@position_blue.route('/add', methods=['POST'])
@check_permission('sys:position:add')
def add():
    """新增岗位"""
    from src.modules.system.position.service import add_position
    from src.modules.system.position.schema import PositionForm
    data = parse_request_body(request, PositionForm)
    return add_position(data)


# ============================================================
# 更新岗位
# ============================================================
@position_blue.route('/update', methods=['PUT'])
@check_permission('sys:position:update')
def update():
    """更新岗位信息"""
    from src.modules.system.position.service import update_position
    from src.modules.system.position.schema import PositionForm
    data = parse_request_body(request, PositionForm)
    return update_position(data)


# ============================================================
# 删除岗位
# ============================================================
@position_blue.route('/delete/<int:id>', methods=['DELETE'])
@check_permission('sys:position:delete')
def delete(id):
    """根据ID删除单个岗位"""
    from src.modules.system.position.service import delete_position
    return delete_position(id)


# ============================================================
# 设置岗位状态
# ============================================================
@position_blue.route('/status', methods=['PUT'])
@check_permission('sys:position:status')
def status():
    """修改岗位状态(启用/禁用)"""
    from src.modules.system.position.service import update_position_status
    from src.modules.system.position.schema import PositionStatusForm
    data = parse_request_body(request, PositionStatusForm)
    return update_position_status(data)


# ============================================================
# 批量删除岗位
# ============================================================
@position_blue.route('/batchDelete', methods=['DELETE'])
@check_permission('sys:position:batchDelete')
def batch_delete():
    """批量删除岗位"""
    from src.modules.system.position.service import batch_delete_positions
    id_list = parse_id_list(request)
    return batch_delete_positions(id_list)

装饰器说明

装饰器 作用 位置
@position_blue.route() 定义 HTTP 方法和路径 最外层
@check_permission('sys:position:page') RBAC 权限校验 路由装饰器之后

装饰器顺序必须严格遵守:路由 → 权限。顺序错误会导致功能异常。

权限字符串命名规范

sys:{module}:{action}
动作 HTTP 方法 说明
page GET 分页查询
detail GET 详情查询
list GET 列表查询
add POST 新增
update PUT 更新
delete DELETE 单条删除
batchDelete DELETE 批量删除
status PUT 状态变更

请求参数解析

from src.common.utils.request import parse_request_body, parse_id_list

# 解析请求体
data = parse_request_body(request, PositionForm)

# 解析ID列表
id_list = parse_id_list(request)
函数 作用
parse_request_body(request, FormClass) 从请求体解析 JSON 并校验
parse_id_list(request) 从请求体解析 ID 数组

响应封装

  • Service 返回 R 对象的(如 add_position、update_position):直接 return
  • Service 返回原始数据的(如 get_position_detail):用 R.ok(data=...) 包装

模块注册

在 src/routes/v1.py 中注册模块:

from src.modules.system.position.router import position_blue

BLUEPRINTS = [
    # ... 其他模块
    position_blue,
    # ... 其他模块
]

开发要点

  1. Router 层不含业务逻辑:仅做路由定义、权限校验和参数绑定
  2. 装饰器顺序:路由 → 权限
  3. 使用 parse_request_body 解析请求体:自动执行 WTForms 校验
  4. 使用 parse_id_list 解析批量操作的 ID 数组
  5. Service 函数使用延迟导入:避免循环引用
  6. 权限字符串与代码完全一致:确保权限校验正确

总结

Router 层是 HTTP 请求的入口,负责路由定义、权限校验和参数绑定,不含业务逻辑。装饰器顺序固定为路由 → 权限,使用 parse_request_body 解析请求体,使用 parse_id_list 解析批量操作的 ID 数组。Service 函数使用延迟导入,避免循环引用。