# **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。 * **预加载**: 包含外键的 Serializer,View 层必须配合 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 ` * API Key: `X-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`