Files
cps-develop-docs/ref/drfstd.md
2026-04-01 11:12:48 +08:00

550 lines
27 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# **GTCO\_AI Django REST Framework(DRF) 后端开发规范指南**
**版本**: 2.16
**适用对象**: Python 后端开发团队
**目标**: 明确技术选型,统一代码风格,降低维护成本,保障系统高可扩展性。
**执行策略**: 本规范采用“限制优先”原则。默认不提供多实现方案,优先固定实现路径;未在本文明确允许的做法,一律视为不允许。
**文档定位**: 本文件是开发规范的唯一基准文档。若与其它开发文档冲突,以本文件为准。
**配套文档入口**: `docs/development/index.md`
**专项规范**:
1. 文档管理:`docs/development/documentation_standards.md`
2. Dify 代理:`docs/development/dify_proxy_standards.md`
3. 代码审查:`docs/development/code_review_guidelines.md`
## **0.0 项目红线 (不可变约束)**
以下为当前仓库的强制架构约束,默认长期有效:
1. **版本唯一**:仅允许 `v1` 命名空间,必须通过 `NamespaceVersioning` 解析版本;禁止新增未命名空间路由。
2. **认证唯一入口**:仅允许 `SmartHeaderAuthentication + GTCOAIJWTAuthentication` 组合;禁止在 View 层读取 `Authorization` / `X-API-Key` 做分流。
3. **认证冲突硬拒绝**:同一请求同时携带 Bearer 与 `X-API-Key` 时必须拒绝,禁止降级兼容。
4. **响应统一封装**:仅允许 `StandardResponseRenderer` 统一包装 `code/message/data`;禁止在业务 View 手动拼装统一响应壳。
5. **异常统一出口**:仅允许 `gtcoai_exception_handler` 输出错误结构;禁止各模块自定义返回格式。
6. **组织作用域强隔离**凡组织级数据user/externals查询必须绑定 `request.user.current_organization`;禁止跨组织默认可见。
7. **权限链路固定**:涉及外部资源访问时,必须遵循“系统动作策略 -> 组织角色/成员 -> 用户组授权”顺序,禁止跳步放行。
8. **写操作服务化**:复杂写操作必须下沉到 Service 层View 层仅做编排、参数校验、权限决策。
9. **代理链路无状态**Dify 透明代理禁止落库业务状态,禁止在代理层引入账号同步、审批等副作用逻辑。
10. **变更必须可验证**:涉及权限、认证、代理路径改动时,必须补齐自动化测试并执行真实路由脚本验证。
11. **门禁入口唯一**:合并前质量检查仅允许通过 `scripts/ci/quality_gate.sh` 执行,禁止自定义临时命令替代。
## **0\. 技术栈清单 (Tech Stack)**
本规范强制使用以下库与工具:
| 分类 | 选定库 | 用途 |
| :---- | :---- | :---- |
| **包管理** | uv | Rust 编写的 Python 包管理器,用于替代 pip/poetry |
| **配置管理** | django-split-settings | 多环境配置拆分 |
| **代码质量** | Ruff | 格式化、排序、检查三合一工具 |
| **类型检查** | VS Code (Pylance) | 编辑器实时检查 (CI 不强制 Mypy) |
| **异步视图** | adrf | DRF 的异步扩展 (Async Django REST Framework) |
| **异步任务** | Celery | 后台任务队列 |
| **消息/缓存** | Redis | Celery Broker / Backend 及 Django Cache |
| **性能调试** | django-debug-toolbar | SQL 查询分析 (开发环境) |
| **性能监测** | nplusone | N+1 问题自动检测 |
| **日志系统** | Loguru | JSON 结构化日志 |
| **认证授权** | drf-simplejwt | JWT 认证 |
| **目录认证** | django-auth-ldap | LDAP 认证(生产环境) |
| **API 文档** | drf-spectacular | OpenAPI 3.0 Schema 生成 |
| **测试框架** | pytest-django | 测试运行器 |
| **测试数据** | factory\_boy | 测试数据生成 |
| **并行测试** | pytest-xdist | 多进程测试加速 |
## **1\. 工程化规范 (Engineering)**
### **1.1 依赖管理**
* **工具**: 统一使用 uv。
* 常用命令: uv pip compile (锁定), uv sync (同步)。
* **版本锁定**: 生产环境必须存在 uv.lock 文件。
* **Python 版本**: 强制版本为 **Python 3.11 及以上**(与 `pyproject.toml` 保持一致)。
### **1.2 配置管理 (Settings)**
**禁止**将所有配置写在单个 settings.py 中。**必须**使用 django-split-settings。
**目录结构要求**
settings/
\_\_init\_\_.py \# 入口逻辑
base.py \# 通用配置
components/ \# 模块化配置 (logging.py, drf.py, celery.py)
environments/\# 环境差异化配置 (local.py, prod.py)
* **安全要求**: 密钥 (SECRET\_KEY, DB\_PASSWORD) **必须**从环境变量 (.env) 读取,**严禁**硬编码。
### **1.3 代码规范 (Linting)**
**工具**: 统一使用 **Ruff**
* **配置要求**:
* **格式化**: ruff format
* **检查**: ruff check \--fix
* **行长**: **120** (严禁使用默认的 88\)
* **类型检查**:
* 开发人员需确保 VS Code (Pylance) 无红色报错。
* CI 流水线不运行 Mypy。
## **2\. 命名与风格 (Naming & Style)**
### **2.1 命名表**
| 对象 | 规范 | 示例 |
| :---- | :---- | :---- |
| **App** | 全小写,复数 | users, orders |
| **Model** | PascalCase单数 | User, ProductCategory |
| **Field** | snake\_case | created\_at |
| **Serializer** | Model \+ Serializer | UserSerializer |
| **View** | Resource \+ Action | UserViewSet |
| **URL** | kebab-case | /api/v1/user-profiles/ |
### **2.2 编码习惯**
* **布尔值**: 必须使用 is\_, has\_, allow\_ 前缀。
* **集合变量**: 必须使用复数形式 (users, items)。
## **3\. 模型层规范 (Models)**
### **3.1 基础模型**
**严禁**使用公共抽象基类(如 BaseModel进行隐式继承。所有业务 Model **必须**直接继承 django.db.models.Model并**显式定义**所有需要的字段,包括主键和审计字段。
这种“各写各的”策略是为了保证每个 Model 的定义清晰、独立,便于后续的迁移和重构,避免基类变更带来的全局副作用。
class MyModel(models.Model):
\# 1\. 主键:根据实际需求显式定义,强制使用 UUID 或 BigAutoField
id \= models.BigAutoField(primary\_key=True)
\# 2\. 业务字段
name \= models.CharField(max\_length=100, help\_text="名称")
\# 3\. 审计字段:必须显式书写,严禁省略
created\_at \= models.DateTimeField(auto\_now\_add=True, help\_text="创建时间")
updated\_at \= models.DateTimeField(auto\_now=True, help\_text="更新时间")
class Meta:
verbose\_name \= "我的模型"
verbose\_name\_plural \= verbose\_name
### **3.2 字段定义**
* **Choices**: 强制使用 TextChoices / IntegerChoices 枚举。
* **Null/Blank**: 字符型字段禁止 null=True必须设为 default=''。
* **Help Text**: 所有字段必须填写 help\_text (用于生成文档)。
* **Related Name**: 外键必须指定 related\_name。
### **3.3 数据库约束**
* **Code First**: 严禁手动直连数据库修改结构,一切变更必须通过 Migrations。
* **索引要求**: 凡是涉及 filter, order\_by, ForeignKey 的字段,**必须**加索引。
* **删除策略**: 默认优先使用物理删除;仅当业务明确要求“可恢复”或“审计追溯”时才引入软删除字段。
* **唯一约束**: 若启用软删除,必须使用带条件的唯一约束 (Conditional Unique Constraint)。
class Meta:
constraints \= \[
models.UniqueConstraint(
fields=\['username'\],
name='unique\_active\_username',
condition=models.Q(is\_deleted=False)
)
\]
### **3.4 外部服务凭证与账号模型规范 (Externals Credentials & Accounts)**
适用于第三方代理场景(如 Dify、OpenAI、内部网关等
* **用户-凭证关系**: 必须为一对多(一个用户可维护多个外部凭证)。
* **凭证核心字段**: 至少包含 `service``credential_type``name``secret``is_active`
* **凭证命名**: `name` 必须用于业务可读标识如“生产Dify主Key”
* **唯一约束**: 同一用户下,`(service, credential_type, name)` 必须唯一。
* **密钥存储**: 明文密钥字段必须加密存储(字段级加密或等效方案),禁止日志打印完整密钥。
* **账号绑定**: 若用户直接绑定外部账号,必须与凭证分表管理。账号表用于身份与连接状态,凭证表用于请求鉴权材料。
* **转发读取原则**: 代理请求阶段只按需求读取目标凭证,不在转发层混入账号同步、授权刷新等重逻辑。
## **4\. 序列化层规范 (Serializers)**
### **4.1 编写规范**
* **选型**: 统一使用 ModelSerializer。
* **字段**: 禁止使用 fields \= '\_\_all\_\_',必须显式列出。
* **参数**: 使用 Meta.extra\_kwargs 定义字段参数,保持代码简洁。
### **4.2 职责边界**
* **定位**: 仅负责数据结构转换和基础格式验证。
* **禁止**: save/create/update 方法中**严禁**包含发送邮件、复杂计算、外部调用等业务逻辑。
### **4.3 性能规范**
* **列表接口**: 严禁在列表页使用深层嵌套的 Serializer强制定义 SimpleSerializer。
* **预加载**: 包含外键的 SerializerView 层必须配合 select\_related / prefetch\_related。
* **聚合计算**: **严禁**在 SerializerMethodField 中执行 SQL 聚合 (count/sum)。必须在 View 层使用 annotate 计算完成后传入。
## **5\. 视图与业务层规范 (Views & Logic)**
### **5.1 ViewSet 选型与分层**
**核心原则**: **精准控制与逻辑分层**
* **选型**:
* 标准 CRUD 强制使用 ModelViewSet。
* 定制化业务场景强制选用 GenericViewSet 配合 Mixins 按需组合。
* 严禁直接使用裸的 ViewSet。
* APIView 仅允许用于“非标准资源形态接口”(如 Dify 透明代理、缓存刷新、健康检查);必须补充 `@extend_schema` 且在类注释中说明无法使用 ViewSet 的原因。
* 权限控制边界:只读接口绝不暴露 CreateModelMixin 或 DestroyModelMixin。
* **方法职责表**:
| 方法 | 核心职责 | 规范要求 |
| :---- | :---- | :---- |
| **get\_queryset** | 查数据 \+ 优化 | **必须**实现权限隔离 (如 filter(user=request.user)) 与预加载 (select\_related),杜绝 N+1。 |
| **get\_serializer\_class** | 定格式 (读写分离) | **必须**区分场景list 用极简版create 用校验版retrieve 用全量版。 |
| **get\_permissions** | 定权限 (动作分离) | **必须**区分动作:如 create 允许匿名destroy 必须管理员。 |
| **perform\_create/update** | 写业务 (逻辑下沉) | 仅处理关联逻辑 (如绑定 request.user) 或调用 Service 层。 |
### **5.2 Service 层模式**
View 层仅作为路由与调度的纯粹枢纽,写操作及复杂查询必须封装到 Service 层。
**严禁**重写 create, update, destroy 等主方法来堆砌业务逻辑。
\# views.py
def create(self, request, \*args, \*\*kwargs):
\# ❌ 错误:不要重写 create 方法,破坏了 DRF 标准流
...
def perform\_create(self, serializer):
\# ✅ 正确:使用钩子调用 Service
create\_order\_service(
user=self.request.user,
data=serializer.validated\_data
)
### **5.3 返回与响应规范 (Return & Response)**
**规则 1: 标准 CRUD 不重写 Return**
对于标准的 create, list, retrieve 等方法,**严禁**重写其 return 逻辑。DRF 父类已处理好序列化和状态码。
**规则 2: 自定义 Action 规范**
对于 @action 装饰的方法:
* **状态码**: 必须导入 rest\_framework.status 使用常量,**严禁**使用魔术数字 (200, 404)。
* **返回**: 必须显式返回 Response 对象。
from rest\_framework import status
from rest\_framework.decorators import action
@action(detail=True, methods=\['post'\])
def approve(self, request, pk=None):
order \= self.get\_object()
\# 业务逻辑...
return Response(serializer.data, status=status.HTTP\_200\_OK)
**规则 3: 错误处理 (Raise, Don't Return)**
遇到业务错误,**严禁**手动 return Response(error)。
**必须**直接 raise Exception (如 ValidationError, PermissionDenied)。全局异常处理器会将异常统一格式化。
**规则 4: 统一响应包装**
**严禁**在每个 View 中手动构建 { "code": 0, "data": ... } 结构。
**必须**编写自定义 Renderer 对全局响应进行统一包装。View 层只返回纯粹的业务数据。
相关实现文件位置apps/common/renderers.py。
### **5.4 认证分流规范 (Authentication Routing)**
* **单一职责**: 鉴权头分流必须在认证层处理,固定入口为 `apps.common.authentication.SmartHeaderAuthentication`,禁止在 View 层手动判断 Header。
* **Header 约定**:
* JWT: `Authorization: Bearer <token>`
* API Key: `X-API-Key: <raw_api_key>`
* **冲突请求**: 同时携带 JWT 与 API Key 的请求必须拒绝,固定抛出 `ValidationError`,禁止“优先 JWT”或“优先 API Key”兼容策略。
* **错误一致性**: 认证失败响应必须统一由全局异常处理器格式化,禁止各认证类返回不同结构。
* **日志可观测性**: 中间件应可区分 `jwt/api_key/anonymous` 三类请求并记录认证失败401/403上下文。
### **5.5 LDAP 接入规范 (LDAP Integration)**
* **接入方式**: 通过 Django Authentication Backend 接入 LDAP禁止在 View/Serializer 直接发 LDAP 请求。
* **配置来源**: LDAP 地址、绑定 DN、密码、搜索过滤器必须来源于环境变量。
* **登录模式**: 登录接口应支持 `local/ldap/auto` 模式切换,默认由配置控制优先级。
* **身份落库**: LDAP 登录成功后,需将本地用户标记为 `auth_type=ldap`,并按配置同步基础属性。
* **平台差异**: Windows 开发环境可不强制安装 `python-ldap`,但 Linux 生产环境必须验证 LDAP 依赖可用。
## **6\. 接口设计规范 (API Design)**
### **6.1 URL 路由**
#### **📌 命名空间与版本控制 (Namespace & Versioning)**
全局强制采用 DRF 的 NamespaceVersioning 机制。**DRF 仅通过读取路由的 namespace 属性来判断当前 API 版本**,若配置缺失,会导致 request.version 为空,进而被权限控制层直接拦截返回 **404 Not Found**
**强制执行标准**:
1. **根路由 (urls.py)**:
挂载业务路由时include() 必须包含版本号命名空间(`namespace="v1"`)。当前项目固定结构如下:
\# gtco_ai/urls.py
api\_v1\_patterns \= \[
path("user/", include("apps.user.urls")),
path("external/", include("apps.externals.urls")),
\]
urlpatterns \= \[
path("api/v1/", include((api\_v1\_patterns, "api"), namespace="v1")),
\]
2. **子路由 (apps/xxx/urls.py)**:
每个 APP 的路由文件必须定义 app\_name 变量,否则 Django 无法正确注册命名空间。
\# apps/user/urls.py
app\_name \= "user" \# ✅ 必须存在且在项目中唯一
urlpatterns \= \[
\# ...
\]
3. **反向解析 (Reverse)**:
在代码中生成 URL 时,必须带上版本前缀。
\# ✅ 正确
reverse("v1:user:user-detail", args=\[user.id\])
\# ❌ 错误
reverse("user:user-detail", args=\[user.id\])
#### **📌 路径设计规范**
* **路由前缀**:所有 API 路由必须以 /api/{version}/ 开头(例如 /api/v1/)。
* **末尾斜杠**:统一保留 URL 末尾斜杠 /,与 DRF DefaultRouter 默认行为保持一致。
* **内部自研接口规范**
* **资源命名**URL 路径**必须**使用 kebab-case短横线连接风格例如 /api/v1/user-profiles/。资源集合统一使用名词复数形式。
* **层级结构**URL 层级不超过 3 层,禁止过深嵌套。标准结构:/api/v1/{resource}/{id}/{sub-resource}/。
* **【特批豁免】第三方代理接口 (Proxy API) 规范**
* **背景**:当代理外部系统(如 Dify 知识库等)接口,且前端需复用官方 SDK 或完全对照第三方官方文档时适用。
* **1:1 映射优先**:允许豁免单复数、命名风格和层级深度的限制,**必须保证字面路径的 1:1 映射**(例如:允许使用 snake\_case 的 child\_chunks允许单数 document允许嵌套深度超过 4 层的 /datasets/{id}/documents/{id}/segments/{id}/child\_chunks/)。
* **架构底线约束**:即便进行字面映射,底层代码实现仍**必须**严格依赖 Django / DRF 的标准路由调度体系(利用 DefaultRouter 处理扁平结构,利用 path \+ as\_view() 显式分发深层嵌套)。
### **6.2 响应格式与状态码 (Response & Status Codes)**
**统一响应结构**:
{
"code": 20000, // 业务状态码 (5位)
"message": "success", // 提示信息
"data": { ... } // 业务数据
}
#### **📌 业务状态码设计原则 (A-BB-CC 5位高可扩展标准)**
随着业务的演进与微服务化,状态码需要具备极高的**可扩展性**与清晰的**域划分**。本系统严格执行 **A-BB-CC 5位数标准**
* **A (1位)**: 错误级别 / HTTP 语义映射。
* 2 \= 成功 (Success)
* 4 \= 客户端错误 / 业务校验阻断 (Client Error)
* 5 \= 服务端异常 / 第三方依赖崩溃 (Server Error)
* **BB (2位)**: 业务模块 / 子域划分 (00\~99),最高支持 100 个核心模块。
* 00 \= Common (全局基础)
* 01 \= User / Auth (用户与认证)
* 02 \= Dify (Dify 代理相关的各个模块集合,含知识库、工作流等)
* **【扩展策略】**:如果未来某个超大型模块的错误类型极其复杂、超出了 99 种,**允许为该大模块分配相邻的多个 BB 号段**。
* **CC (2位)**: 具体错误分类序号 (00\~99)。
* 00 \= 该模块的“默认通用错误”或“成功”。
* 01\~99 \= 具体的精细化业务异常。
#### **📌 状态码扩展与开发强制规约**
1. **禁止过度分配 (泛化 vs 特化)**
* **禁止**为每一个表单字段的“必填项校验”单独分配 Code。普通的输入参数异常统一使用 40000 (全局 Bad Request),并在 message 或 data 节点中动态告知前端具体的字段校验失败原因。
* **分配底线**:只有当**前端代码需要利用此 Code 进行特殊的交互逻辑跳转时**才予以分配。例如40102 (账号被冻结) 前端检测到后需要弹出特殊申诉弹窗40201 (Dify API Key未配置) 前端检测到后需要引导至设置页面。
2. **代码物理隔离 (分治策略)**
* **禁止单文件膨胀**:禁止把所有业务 Code 全部堆在 apps/common/status\_code.py 中。
* **规范要求**apps/common/status\_code.py **仅存放 00 模块**的基础状态码。各个业务线独有的状态码,**必须存放于各自 App 的文件内**(例如 apps/dify/knowledge/status\_code.py
### **6.3 分页**
* **默认分页**: 统一采用 LimitOffsetPagination。
* **大数据分页**: 当前仓库未批准引入 Cursor/Keyset 替代方案作为默认行为;所有常规列表接口必须先落地 LimitOffsetPagination。
* **流式分页**: 对于瀑布流场景,统一使用 CursorPagination。
### **6.4 API 文档注解规范 (drf-spectacular / extend_schema)**
* **强制要求**: 所有对外接口(尤其是 `@action` 自定义动作和代理接口)必须显式使用 `@extend_schema`
* **最低字段**: `summary``description``request``responses` 必须完整声明。
* **响应说明**: 对透传接口应使用 `OpenApiResponse` 明确说明“上游原样透传”,避免文档误导前端。
* **禁止事项**: 禁止仅依赖自动推断导致关键请求字段(如 `method``route``path_params`)在文档中缺失。
## **7\. 性能与异步规范 (Performance & Async)**
### **7.1 数据库查询**
* **N+1 问题**: 开发环境必须安装 nplusone 插件CI 检测到 N+1 报错即为不合格。
* **批量操作**: 循环插入/更新必须使用 bulk\_create / bulk\_update。
* **迭代**: 遍历大表必须使用 .iterator()。
### **7.2 异步视图**
* **场景限制**: 仅在 **高并发 I/O 密集型** (如聚合多个第三方 API) 场景下使用。
* **实现方案**: 统一使用 adrf 库。
* **禁止事项**: 严禁在 async def 中运行 CPU 密集型任务 (Pandas/图片处理)。严禁混用同步 ORM 方法。
### **7.3 异步任务**
* **选型**: 统一使用 Celery \+ Redis。
* **剥离标准**: 耗时 \> 200ms 的逻辑 (邮件、报表、AI推理) 必须剥离到后台任务。
* **事务安全**: 必须使用 transaction.on\_commit 触发任务。
### **7.4 缓存**
* **组件**: 统一使用 django-redis。
* **策略**: 强制使用 Cache-Aside (旁路缓存) 策略。
## **8\. 日志与异常规范 (Logs)**
### **8.1 异常处理**
**配置**:
1. 必须在 settings.py 中配置 EXCEPTION\_HANDLER 指向 `apps.common.exceptions.gtcoai_exception_handler`
2. 异常处理器需将所有 DRF 异常 (APIException) 和 未知异常 (Exception) 统一转化为标准 JSON 响应结构。
### **8.2 日志配置**
**工具**: 统一使用 Loguru。
**配置要求**:
1. **拦截**: 必须通过 InterceptHandler 接管 Django 原生日志。
2. **输出**:
* 控制台: 彩色文本。
* 文件: JSON 格式 (serialize=True),便于采集。
## **9\. 认证与权限规范 (Auth)**
### **9.1 认证架构 (Authentication Strategy)**
**核心方案**:采用 JWT (JSON Web Token) 作为无状态认证标准,库选型锁定 djangorestframework-simplejwt。
**单点登录 (SSO) 集成**
**架构选型**:强制使用 django-allauth 处理 OAuth 协议握手,配合 dj-rest-auth 暴露 REST 接口。严禁手写 OAuth2 流程。
**交互流程**:采用 "Authorization Code" 模式。前端仅负责获取第三方(如 Google/GitHub的 code后端负责用 code 换取用户信息并颁发本系统的 JWT。严禁后端直接信任前端传来的第三方用户信息。
**账号融合**:强制实施“基于邮箱的自动关联”策略。无论用户是通过账号密码注册,还是通过 SSO 登录,只要邮箱一致,必须关联到同一个 User 实体,确保用户身份唯一性。
### **9.2 Token安全与管理 (Token Engineering)**
**载荷 (Payload) 规范**
**最小化原则**Token 内仅允许携带非敏感的身份标识(如 user\_id, role, username
**扩展方式**:必须通过继承 TokenObtainPairSerializer 并重写 get\_token 方法注入自定义声明。严禁修改库源码或在 View 层手动拼凑 Token。
**生命周期管理**
双 Token 机制:强制启用 Access Token 与 Refresh Token 分离。
* Access Token 有效期:**固定 24 小时**(与 `settings/components/drf.py` 保持一致)。
* Refresh Token 有效期:**固定 7 天**。
**黑名单机制**:生产环境必须启用 Blacklist 应用,确保用户注销或修改密码后,旧的 Refresh Token 立即失效。
### **9.3 权限分层治理 (Permission Governance)**
**默认策略**:实施 "Default Deny" (默认拒绝) 策略。全局配置 (DEFAULT\_PERMISSION\_CLASSES) 必须设为 IsAuthenticated仅对特定公开接口如注册、登录、健康检查显式配置 AllowAny。
在 ViewSet 中,严禁使用静态的 permission\_classes 列表覆盖所有方法。
**动作级权限 (Action-Based)**
**实现规范**:必须重写 get\_permissions() 方法,根据 self.action如 create, list, destroy动态分配权限例如所有人可注册登录用户可查看仅管理员可删除
**系统动作策略优先 (System Policy First)**:当接口涉及“资源 + 动作”权限时,必须先校验系统级资源动作策略(资源支持动作 + 系统禁用动作),再进入组织角色与成员授权判断。严禁仅依赖成员授权直接放行不受系统支持的动作。
**对象级权限 (Object-Level)**
涉及“只能操作自己的数据”或“组内可见”的场景,严禁在 View 的业务逻辑中写 if user \== owner。
**实现规范**:必须自定义继承自 BasePermission 的权限类,并重写 has\_object\_permission 方法,将鉴权逻辑与业务逻辑物理隔离。
### **9.4 安全加固 (Security Hardening)**
**CSRF 防护**:所有 POST/PUT/PATCH/DELETE 请求必须包含 CSRF Token全局配置 (CSRF\_COOKIE\_HTTPONLY) 设为 True。
**防爆破 (Throttling)**:所有认证相关接口(登录、注册、刷新 Token、SSO 回调)必须配置高强度的限流策略(如 AnonRateThrottle防止暴力破解。
**错误模糊化**:认证失败时,统一返回“用户名或密码错误”或“认证失败”,严禁明确提示“用户不存在”或“密码错误”,防止用户信息泄露。
## **10\. 测试规范 (Testing)**
### **10.1 工具链**
* **Runner**: 统一使用 pytest \+ pytest-django。
* **Data**: 统一使用 factory\_boy。
* **Client**: 统一使用 APIClient (DRF)。
* **Coverage**: 统一使用 pytest-cov。
### **10.2 编写规范**
* **Fixture**: 通用对象定义在 conftest.py。
* **Mock**: 外部 API 调用**必须** Mock禁止在测试中发起真实网络请求。
* **真实链路验证例外**: 对 `apps/externals` 的代理/权限链路改动,允许并要求使用 `scripts/external/` 下脚本做“联调验证”,但该验证不替代 pytest。
* **提交门禁**: 上述改动在合并前必须同时满足“脚本联调通过 + 相关 pytest 用例通过”。
* **执行**: CI 环境需开启 pytest-xdist 并行执行。
### **10.3 当前项目固定测试命令 (提交前最低要求)**
1. 外部资源治理与代理相关改动:必须运行 `pytest apps/externals/tests.py`
2. 用户/组织/认证相关改动:必须运行 `pytest apps/user/tests.py`
3. 同时改动 `user + externals`:必须同时运行以上两组用例,禁止只跑局部单测后直接提交。
### **10.4 CI 固定执行链路 (禁止绕过)**
1. 本仓库唯一质量门禁脚本:`scripts/ci/quality_gate.sh`
2. 脚本执行顺序固定为:`ruff format --check` -> `ruff check` -> `pytest apps/user/tests.py` -> `pytest apps/externals/tests.py`
3. 当前阶段Docker 开发流程)提交前必须本地执行该脚本;任一步失败不得提交。
4. CI 启用后,流水线必须在构建前执行该脚本;任一步失败即阻断后续阶段。
5. 禁止在本地或 CI 中通过 `|| true`、跳过测试参数、或删改步骤顺序绕过门禁。
### **10.5 提交审查规范**
代码审查流程与输出模板统一见:
`docs/development/code_review_guidelines.md`
## **11\. 文档管理规范 (Documentation)**
本章节拆分为独立文档,减少主规范长度并便于专项维护。
详见:`docs/development/documentation_standards.md`
最低强制要求:
1. 核心业务改动必须同步更新测试与文档。
2. OpenAPI 注解必须完整(`@extend_schema`)。
3. 文档冲突时以 `docs/development/standards.md` 为准。
## **12\. Dify 代理模块规范 (Dify Proxy Module)**
本章节拆分为独立文档,避免主规范过长。
详见:`docs/development/dify_proxy_standards.md`
最低强制要求:
1. 代理层无状态、无业务存储。
2. 路由常量统一由 `interfaces.py` 维护,禁止硬编码 URL。
3. 保持全异步链路并统一错误处理。
## **13\. 全局权限治理落地文档**
权限治理的可执行实施方案角色矩阵、Scope 规范、分阶段改造、验收清单)见:
`docs/plans/permission_governance_plan.md`