Skip to content

Router 层(Flask Blueprint) ​

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

文件位置 ​

src/modules/system/position/router.py

完整代码 ​

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

python
"""
岗位管理控制器模块
=============================================================

提供岗位(Position)相关的API接口,包括:
- 岗位分页查询
- 岗位详情查询
- 岗位添加、更新、删除
- 岗位状态设置
- 岗位数据列表获取
"""
from flask import Blueprint, request

from src.middleware import check_demo, operation_log
from src.core.permission import check_permission
from src.modules.system.position import service as position
from src.common.utils.request import parse_batch_ids, parse_request_body

from src.core import response as R

position_blue = Blueprint('position', __name__, url_prefix='/position')


# ============================================================
# 岗位分页查询
# ============================================================

@position_blue.route('/page', methods=["GET"])
@check_permission("sys:position:page")
@operation_log("岗位管理", "查询")
def page():
    """
    查询岗位分页数据

    Returns:
        JSON: 岗位分页数据,包含 records(数据列表)、total(总记录数)等
    """
    return R.ok(data=position.get_position_page(request.args))


# ============================================================
# 岗位详情查询
# ============================================================

@position_blue.route('/detail/<int:id>', methods=["GET"])
@check_permission("sys:position:detail")
@operation_log("岗位管理", "详情")
def detail(id):
    """
    查询岗位详情

    Args:
        id: 岗位ID

    Returns:
        JSON: 岗位详细信息
    """
    data = position.get_position_detail(id)
    return R.ok(data=data)


# ============================================================
# 岗位添加
# ============================================================

@position_blue.route('/add', methods=["POST"])
@check_permission("sys:position:add")
@check_demo
@operation_log("岗位管理", "新增")
def add():
    """
    添加岗位

    Returns:
        JSON: 操作结果
    """
    json_data, err = parse_request_body()
    if err:
        return R.failed(msg=err)
    position.add_position(json_data)
    return R.ok(msg="添加成功")


# ============================================================
# 岗位更新
# ============================================================

@position_blue.route('/update', methods=["PUT"])
@check_permission("sys:position:update")
@check_demo
@operation_log("岗位管理", "修改")
def update():
    """
    更新岗位

    Returns:
        JSON: 操作结果
    """
    json_data, err = parse_request_body()
    if err:
        return R.failed(msg=err)
    position.update_position(json_data)
    return R.ok(msg="更新成功")


# ============================================================
# 岗位删除
# ============================================================

@position_blue.route('/delete/<string:id>', methods=["DELETE"])
@check_permission("sys:position:delete")
@check_demo
@operation_log("岗位管理", "删除")
def delete(id):
    """
    删除岗位

    Args:
        id: 岗位ID(支持逗号分隔的多个ID)

    Returns:
        JSON: 操作结果
    """
    count = position.delete_positions(id)
    return R.ok(msg=f"本次共删除{count}条数据")


# ============================================================
# 岗位批量删除
# ============================================================

@position_blue.route('/batchDelete', methods=["DELETE"])
@check_permission("sys:position:batchDelete")
@check_demo
@operation_log("岗位管理", "批量删除")
def batch_delete():
    """
    批量删除岗位

    Request Body:
        [1, 2, 3]  # 岗位ID数组

    Returns:
        JSON: 操作结果
    """
    id_str, err = parse_batch_ids()
    if err:
        return err
    count = position.delete_positions(id_str)
    return R.ok(msg=f"本次共删除{count}条数据")


# ============================================================
# 岗位状态设置
# ============================================================

@position_blue.route('/status', methods=["PUT"])
@check_permission("sys:position:status")
@check_demo
@operation_log("岗位管理", "状态变更")
def status():
    """
    设置岗位状态

    Returns:
        JSON: 操作结果
    """
    json_data, err = parse_request_body()
    if err:
        return R.failed(msg=err)
    position.update_position_status(json_data)
    return R.ok(msg="设置成功")


# ============================================================
# 岗位列表获取(无分页)
# ============================================================

@position_blue.route('/list', methods=["GET"])
@check_permission("sys:position:list")
@operation_log("岗位管理", "查询")
def get_position_list():
    """
    获取岗位数据列表(无分页)

    用于下拉选择框,支持 name 模糊匹配。

    Returns:
        JSON: 岗位列表数据
    """
    result = position.get_position_list(request.args)
    return R.ok(data=result)

代码解析 ​

Blueprint 实例 ​

python
position_blue = Blueprint('position', __name__, url_prefix='/position')

每个 router 文件创建一个独立的 Blueprint 实例,后续在 src/routes/v1.py 中统一注册。

装饰器说明 ​

装饰器作用位置
@position_blue.route()定义 HTTP 方法和路径最外层
@check_permission('sys:position:page')RBAC 权限校验路由装饰器之后
@check_demo演示模式拦截(写操作)权限装饰器之后
@operation_log("岗位管理", "查询")操作日志记录最内层

装饰器顺序必须严格遵守:路由 → 权限 → 演示模式 → 操作日志。

权限字符串命名规范 ​

sys:{module}:{action}
动作HTTP 方法说明
pageGET分页查询
detailGET详情查询
listGET列表查询(无分页)
addPOST新增
updatePUT更新
deleteDELETE单条删除
batchDeleteDELETE批量删除
statusPUT状态变更

参数解析 ​

python
# 解析请求体 JSON(POST/PUT)
json_data, err = parse_request_body()
if err:
    return R.failed(msg=err)

# 解析批量删除的 ID 数组(DELETE)
id_str, err = parse_batch_ids()
if err:
    return err

# 获取查询参数(GET)
params = request.args  # 如 request.args.get('name')

响应封装 ​

python
# 成功响应
R.ok(data=data)           # 返回数据
R.ok(msg="添加成功")       # 返回消息
R.ok(data=data, msg="ok") # 同时返回数据和消息

# 失败响应
R.failed(msg="参数错误")   # 返回错误消息

开发要点 ​

  1. 只需两步注册:一行导入 Blueprint,一行添加到 BLUEPRINTS 列表
  2. prefix 与模块目录名保持一致:便于代码导航
  3. 所有业务蓝图都挂在 v1 路由组下:自动享受 login_required 认证保护
  4. 装饰器顺序:路由 → @check_permission → @check_demo → @operation_log
  5. Router 层不处理业务逻辑:只做参数解析和响应封装,业务逻辑委托 Service 层

总结 ​

Router 层通过 Flask Blueprint 定义路由,使用 @check_permission 实现 RBAC 权限控制,@check_demo 拦截演示模式写操作,@operation_log 自动记录操作日志。参数解析通过 parse_request_body() / parse_batch_ids() 完成,响应封装通过 R.ok() / R.failed() 统一格式。

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