-
Notifications
You must be signed in to change notification settings - Fork 0
01 api conventions and envelope
本文档说明 LIMIS 后端(Django + Django REST framework)对外 HTTP API 的通用约定,与仓库实现一致。
| 项目 | 说明 |
|---|---|
| API 前缀 | /api/v1/ |
| 内容类型 |
application/json(文件上传除外) |
| 认证 | 除登录、刷新令牌等白名单接口外,请求头需携带 JWT:Authorization: Bearer <access_token>
|
| OpenAPI |
/api/schema/(原始 Schema);/api/docs/(Swagger UI);/api/redoc/(ReDoc) |
各业务模块挂载在 api/v1/<模块>/ 下,例如 system、projects、commissions 等(见根路由 backend/limis/urls.py)。
多数列表(分页)、写操作及部分自定义接口采用统一业务信封:
{
"code": 200,
"message": "success",
"data": { }
}-
code:业务状态码,成功时常见为200(查询/更新/删除成功)或201(创建成功)。类型应为数字;若经网关被序列化为字符串(如"200"),前端frontend/src/utils/request.ts会兼容解析后再解包data。 -
message:人类可读说明。 -
data:实际载荷(对象、列表或分页结构)。
列表且启用分页时,data 为分页对象:
{
"code": 200,
"message": "success",
"data": {
"count": 135,
"page": 1,
"page_size": 20,
"results": [ ]
}
}查询参数:
-
page:页码(从 1 开始) -
page_size:每页条数(上限 100,见backend/core/pagination.py)
继承 core.views.BaseModelViewSet 的 ViewSet 对 create / update 返回信封;destroy 返回 code: 200 与固定文案。
创建成功(HTTP 201)示例:
{
"code": 201,
"message": "创建成功",
"data": {
"id": 42,
"name": "示例项目"
}
}更新成功(HTTP 200)示例:
{
"code": 200,
"message": "更新成功",
"data": { }
}删除成功(软删或硬删,HTTP 200)示例:
{
"code": 200,
"message": "删除成功"
}以下场景不使用 { code, message, data } 三层结构,返回体为 DRF 默认或自定义扁平 JSON:
-
登录
POST /api/v1/system/login/:返回access、refresh、user(见《认证与令牌》文档)。 -
当前用户
GET /api/v1/system/me/:直接返回用户序列化字段 +permissions数组。 -
登出、改密 等:常见为
{ "detail": "..." }。 - 单条资源 GET(retrieve):多数 ViewSet 未统一包信封,直接为资源 JSON 对象。
-
SimpleJWT 刷新:
POST /api/v1/system/token/refresh/返回access(及轮换时的refresh),见 simplejwt 默认行为。
前端 Axios 拦截器仅当响应体含 code 字段 时按信封解析;否则将整个 body 当作业务数据返回。集成新接口时务必区分「信封接口」与「裸 JSON」。
全局异常处理:core.exceptions.custom_exception_handler。
{
"code": 422,
"message": "字段说明:第一条可读错误",
"errors": { }
}-
code:可与 HTTP 状态码一致(如 400、403、404、422);也用于业务异常自定义码。 -
message:主错误信息;校验类错误会尽量拼接「字段名 + 首条说明」便于前端直接展示。 -
errors:可选。存在时多为 DRFValidationError的detail结构(字段级错误字典或列表)。
HTTP 状态码通常与 code 对齐(见 _build_error_response);若 code 非合法 HTTP 码会回退为 400。
| 状态 | 含义 |
|---|---|
| 400 | 错误请求、业务异常(BusinessException) |
| 401 | 未认证或令牌无效(JWT / 会话版本不一致等) |
| 403 | 无权限 |
| 404 | 资源不存在 |
| 409 | 幂等冲突等(见下) |
| 422 | 数据校验失败(含 errors) |
| 429 | 限流(如修改密码) |
部分视图仍直接返回 {"detail": "..."}(未经过统一 code 包装)。前端在 Axios 错误回调中会尝试读取 detail 或 message。
对 POST / PUT / PATCH / DELETE 且路径以 /api/v1/ 开头的请求,可携带:
Idempotency-Key: <uuid 或客户端生成的唯一字符串,建议 ≤128 字符>中间件 core.middleware.IdempotencyMiddleware 会按用户 + 方法 + 路径 + 键去重;重复成功请求可重放缓存的响应(响应头 X-Idempotency-Replayed: true)。冲突时可能返回:
{
"code": 409,
"message": "幂等键已被不同请求体占用"
}登录与刷新令牌路径不参与幂等键逻辑(与前端 frontend/src/utils/request.ts 中跳过规则一致)。
需登录的 ViewSet 常设置:
-
lims_module:模块编码(如system、project、commission)。 -
lims_action_map:自定义 action 到权限动作(view/create/edit/delete)的映射。
未配置 lims_module 时仅校验是否登录。超级用户绕过模块校验。详见 backend/core/permissions.py。
-
信封解包:成功且
code为 200/201 时,拦截器返回data(若存在),调用方拿到的已是内部载荷。 -
字符串
code:网关若将code改为字符串"200",仍需能解包(项目已处理)。 -
嵌套
data:爬虫等接口可能出现data内再包一层,前端可用frontend/src/utils/apiField.ts中的unwrapCrawlPayload等工具剥层。 -
snake_case / camelCase:后端序列化多为 snake_case;若某处为 camelCase,读取字段时建议双读兼容(见
apiField)。
| 内容 | 路径 |
|---|---|
| 根路由 | backend/limis/urls.py |
| 统一分页信封 | backend/core/pagination.py |
| CRUD 信封 |
backend/core/views.py(BaseModelViewSet) |
| 异常格式 | backend/core/exceptions.py |
| 幂等与审计中间件 | backend/core/middleware.py |
| 前端 Axios 与信封 | frontend/src/utils/request.ts |