Skip to content

公共与共享服务

API 事实来源:Django 后端自动文档

为什么这些能力放在公共层

common 放置系统级能力:配置、上传、分页、任务状态和 OpenAPI 包装。services/ 放置跨 app 可复用但不拥有业务状态的服务。

代码入口:

  • backend/common/models.py
  • backend/common/models_task.py
  • backend/common/views.py
  • backend/common/views_task.py
  • backend/common/pagination.py
  • backend/common/middleware/
  • backend/services/

系统配置

  • SystemConfig 是单例配置,当前承载季节作息和学期开始日期。
  • 季节切换只能由 superadmin 执行。
  • 季节配置影响课程时间缓存;修改配置逻辑时要同时看课程服务。

任务状态为什么不用 Redis 归属键

  • 后台任务状态以 TaskRecord 为事实来源。
  • /api/v1/tasks/ 是只读 viewset,支持列表和详情。
  • 非管理员只看自己的任务;superadminsecretary 可看全部任务。
  • 状态值使用数据库枚举:pendingstartedsuccessfailure
  • 旧的 Redis task_owner:<task_id> 归属方案已废弃。任务状态和归属放在数据库中,便于权限过滤、审计和进程重启后的恢复。

上传的当前状态

  • 当前上传端点直接写 LOCAL_UPLOAD_DIR,返回 URL 由 LOCAL_UPLOAD_URL_PREFIX 拼接。
  • services/file_storage.py 已有本地/S3 双后端抽象,但上传端点尚未接入。
  • 上传改造前先决定:继续保持本地上传语义,还是正式迁移到 storage abstraction。两条路径的部署、URL、权限和回滚方式不同。

分页与请求上下文

  • 默认分页类是 DefaultPagination,最大页大小为 200。
  • RequestTimezoneMiddlewareX-Timezone 激活请求时区。
  • OperationLogContextMiddlewareCurrentRoleMiddleware 虽不在 common/,但属于系统级请求上下文能力。

共享代码的判断标准

  • 公共层可以服务业务模块,但反向依赖具体业务模块会让系统边界变模糊。
  • 单模块逻辑留在所属 app;只有稳定复用于多个模块的能力才放入 services/
  • OpenAPI envelope hook 会影响自动文档和前端生成类型,修改后需要同时验证这两端。