# 模型验证规则 **本文档引用的文件** - [backend/app/models/models.py](file://backend/app/models/models.py) - [backend/app/models/finance.py](file://backend/app/models/finance.py) - [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py) - [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py) - [backend/app/api/v1/indicators.py](file://backend/app/api/v1/indicators.py) - [backend/app/api/v1/assessments.py](file://backend/app/api/v1/assessments.py) - [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py) - [backend/app/services/indicator_service.py](file://backend/app/services/indicator_service.py) - [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py) - [backend/app/main.py](file://backend/app/main.py) - [backend/requirements.txt](file://backend/requirements.txt) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构概览](#架构概览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排除指南](#故障排除指南) 9. [结论](#结论) ## 简介 本文件系统性梳理了医院绩效系统中的模型验证规则,涵盖数据模型的验证机制,包括字段类型验证、范围限制、格式检查和业务规则验证。文档重点解释了以下三个层面的验证实现: - Pydantic 模型验证:通过 Pydantic 的 Field 参数与类型注解实现请求体与响应体的数据校验。 - SQLAlchemy 约束验证:通过数据库层的列类型、索引与 CheckConstraint 实现数据完整性约束。 - 业务逻辑验证:通过服务层与 API 层的业务规则检查,确保数据在业务语义上的正确性。 同时,文档阐述了验证错误的处理方式与用户友好的错误信息设计,并提供验证规则的扩展方法与自定义验证器的实现建议。 ## 项目结构 后端采用 FastAPI + SQLAlchemy 异步 ORM 的架构,数据模型位于 models 目录,Pydantic 数据模式位于 schemas 目录,API 路由位于 api/v1 目录,业务逻辑位于 services 目录,异常处理与全局配置位于 main.py。 ```mermaid graph TB subgraph "API 层" A1["staff.py"] A2["indicators.py"] A3["assessments.py"] end subgraph "服务层" S1["staff_service.py"] S2["indicator_service.py"] S3["assessment_service.py"] end subgraph "模式层" P1["schemas.py"] end subgraph "模型层" M1["models.py"] M2["finance.py"] end subgraph "核心" C1["main.py"] C2["requirements.txt"] end A1 --> S1 A2 --> S2 A3 --> S3 S1 --> M1 S2 --> M1 S3 --> M1 A1 --> P1 A2 --> P1 A3 --> P1 M1 --> C2 M2 --> C2 P1 --> C2 C1 --> A1 C1 --> A2 C1 --> A3 ``` **图表来源** - [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L1-L124) - [backend/app/api/v1/indicators.py](file://backend/app/api/v1/indicators.py#L1-L142) - [backend/app/api/v1/assessments.py](file://backend/app/api/v1/assessments.py#L1-L166) - [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L1-L112) - [backend/app/services/indicator_service.py](file://backend/app/services/indicator_service.py#L1-L197) - [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L114-L262) - [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L1-L743) - [backend/app/models/models.py](file://backend/app/models/models.py#L1-L438) - [backend/app/models/finance.py](file://backend/app/models/finance.py#L1-L79) - [backend/app/main.py](file://backend/app/main.py#L50-L91) - [backend/requirements.txt](file://backend/requirements.txt#L1-L16) **章节来源** - [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L1-L124) - [backend/app/api/v1/indicators.py](file://backend/app/api/v1/indicators.py#L1-L142) - [backend/app/api/v1/assessments.py](file://backend/app/api/v1/assessments.py#L1-L166) - [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L1-L112) - [backend/app/services/indicator_service.py](file://backend/app/services/indicator_service.py#L1-L197) - [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L114-L262) - [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L1-L743) - [backend/app/models/models.py](file://backend/app/models/models.py#L1-L438) - [backend/app/models/finance.py](file://backend/app/models/finance.py#L1-L79) - [backend/app/main.py](file://backend/app/main.py#L50-L91) - [backend/requirements.txt](file://backend/requirements.txt#L1-L16) ## 核心组件 - Pydantic 数据模式:通过 Field 的类型、长度、数值范围、正则表达式等参数实现字段级验证;通过枚举类型保证取值域的正确性;通过 model_config 的 from_attributes 控制 ORM 对象到 Pydantic 模式的转换。 - SQLAlchemy 模型:通过列类型(String、Integer、Numeric、Boolean、DateTime、Enum)、索引与 CheckConstraint 实现数据库层约束;通过外键关系与级联策略保证参照完整性。 - API 层:在路由函数中接收 Pydantic 模式作为请求体,自动触发 Pydantic 验证;在业务逻辑允许范围内进行额外的业务规则检查,并抛出 HTTP 异常。 - 服务层:封装 CRUD 与业务逻辑,负责数据一致性与业务规则的执行;在必要时进行跨实体的约束检查。 - 异常处理:全局注册异常处理器,捕获并记录验证错误与业务异常,返回统一的错误信息。 **章节来源** - [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L49-L60) - [backend/app/models/models.py](file://backend/app/models/models.py#L62-L85) - [backend/app/models/finance.py](file://backend/app/models/finance.py#L45-L74) - [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L68-L81) - [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L69-L91) - [backend/app/main.py](file://backend/app/main.py#L58-L74) ## 架构概览 下图展示了从 API 请求到数据库写入的完整验证链路,包括 Pydantic 验证、业务规则检查与数据库约束验证。 ```mermaid sequenceDiagram participant Client as "客户端" participant API as "API 路由" participant Pyd as "Pydantic 模式" participant Svc as "服务层" participant DB as "SQLAlchemy 模型" participant SQL as "数据库" Client->>API : "POST /staff" API->>Pyd : "StaffCreate 验证" Pyd-->>API : "验证通过/错误" API->>Svc : "调用业务逻辑" Svc->>DB : "构造模型实例" DB->>SQL : "执行插入/更新" SQL-->>DB : "约束检查结果" DB-->>Svc : "返回持久化结果" Svc-->>API : "返回业务结果" API-->>Client : "统一响应" ``` **图表来源** - [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L68-L81) - [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L107-L124) - [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L69-L76) - [backend/app/models/models.py](file://backend/app/models/models.py#L88-L114) ## 详细组件分析 ### Pydantic 模型验证 - 字段类型与长度验证:通过 Field 的类型注解与 max_length/min_length 限制字符串长度;例如员工工号、姓名、职位、电话、邮箱等字段均设置了长度限制。 - 数值范围验证:通过 ge(大于等于)、le(小于等于)、gt(大于)等参数限制数值范围;例如基本工资、绩效系数、权重、最高分值、年份、月份等。 - 枚举验证:通过 str + Enum 的组合确保取值域的正确性;例如科室类型、员工状态、指标类型、考核状态等。 - 正则表达式验证:通过 pattern 参数对字符串格式进行约束;例如用户角色字段使用正则限制合法取值。 - 响应模式转换:通过 model_config(from_attributes=True) 将 ORM 对象直接转换为 Pydantic 模式,避免重复映射。 ```mermaid classDiagram class StaffBase { +employee_id : str +name : str +department_id : int +position : str +title : Optional[str] +phone : Optional[str] +email : Optional[str] +base_salary : float +performance_ratio : float } class StaffCreate { +status : StaffStatus +hire_date : Optional[datetime] } class StaffResponse { +id : int +status : StaffStatus +hire_date : Optional[datetime] +created_at : datetime +updated_at : datetime +department_name : Optional[str] } StaffCreate --|> StaffBase StaffResponse --|> StaffBase ``` **图表来源** - [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L107-L150) **章节来源** - [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L64-L98) - [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L107-L150) - [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L315-L345) ### SQLAlchemy 约束验证 - 列类型与默认值:通过 String、Integer、Numeric、Boolean、DateTime、Enum 等类型定义字段属性与默认值;例如 Numeric(10,2) 用于金额与分数的精确存储。 - 索引优化:为常用查询字段添加索引,提升查询性能;例如科室类型、状态、年月组合等。 - CheckConstraint:通过 CheckConstraint 在数据库层强制业务约束;例如指标权重必须大于 0,财务金额必须大于等于 0。 - 外键关系:通过 ForeignKey 建立实体间的参照关系,配合级联策略保证数据一致性。 ```mermaid erDiagram STAFF { int id PK string employee_id UK string name int department_id FK string position string title string phone string email numeric base_salary numeric performance_ratio enum status date hire_date } DEPARTMENTS { int id PK string name string code UK enum dept_type int parent_id FK int level int sort_order boolean is_active } INDICATORS { int id PK string name string code UK enum indicator_type enum bs_dimension numeric weight numeric max_score numeric target_value string target_unit text calculation_method text assessment_method text deduction_standard text data_source string applicable_dept_types boolean is_veto boolean is_active } ASSESSMENTS { int id PK int staff_id FK int period_year int period_month string period_type numeric total_score numeric weighted_score enum status int assessor_id FK int reviewer_id FK datetime submit_time datetime review_time text remark } ASSESSMENT_DETAILS { int id PK int assessment_id FK int indicator_id FK numeric actual_value numeric score text evidence text remark } SALARY_RECORDS { int id PK int staff_id FK int period_year int period_month numeric base_salary numeric performance_score numeric performance_bonus numeric deduction numeric allowance numeric total_salary string status text remark } DEPARTMENTS ||--o{ STAFF : "拥有" STAFF ||--o{ ASSESSMENTS : "被考核" ASSESSMENTS ||--o{ ASSESSMENT_DETAILS : "包含" INDICATORS ||--o{ ASSESSMENT_DETAILS : "被评分" ``` **图表来源** - [backend/app/models/models.py](file://backend/app/models/models.py#L62-L114) - [backend/app/models/models.py](file://backend/app/models/models.py#L117-L146) - [backend/app/models/models.py](file://backend/app/models/models.py#L149-L178) - [backend/app/models/models.py](file://backend/app/models/models.py#L181-L202) - [backend/app/models/models.py](file://backend/app/models/models.py#L205-L230) - [backend/app/models/finance.py](file://backend/app/models/finance.py#L45-L74) **章节来源** - [backend/app/models/models.py](file://backend/app/models/models.py#L143-L146) - [backend/app/models/finance.py](file://backend/app/models/finance.py#L68-L74) ### 业务逻辑验证 - API 层业务规则:在创建与更新接口中,先进行 Pydantic 验证,再进行业务规则检查;例如创建员工前检查工号唯一性,创建指标前检查编码唯一性。 - 服务层业务规则:在服务层进行更复杂的业务一致性检查;例如更新考核记录时,仅允许在草稿或已驳回状态下进行修改,并重新计算总分与加权分。 - 统一错误处理:通过 HTTPException 抛出业务错误,结合全局异常处理器记录日志并返回统一的错误响应。 ```mermaid flowchart TD Start(["开始"]) --> ValidatePyd["Pydantic 验证"] ValidatePyd --> PydanticOK{"验证通过?"} PydanticOK --> |否| ReturnError["返回验证错误"] PydanticOK --> |是| BusinessCheck["业务规则检查"] BusinessCheck --> BusinessOK{"业务规则通过?"} BusinessOK --> |否| RaiseHTTP["抛出 HTTP 异常"] BusinessOK --> |是| Persist["持久化到数据库"] Persist --> Done(["结束"]) ReturnError --> Done RaiseHTTP --> Done ``` **图表来源** - [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L75-L78) - [backend/app/api/v1/indicators.py](file://backend/app/api/v1/indicators.py#L78-L81) - [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L114-L151) - [backend/app/main.py](file://backend/app/main.py#L58-L74) **章节来源** - [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L68-L95) - [backend/app/api/v1/indicators.py](file://backend/app/api/v1/indicators.py#L71-L98) - [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L114-L151) - [backend/app/main.py](file://backend/app/main.py#L58-L74) ### 验证错误处理与用户友好信息 - HTTP 异常:在业务规则不满足时,使用 HTTPException 返回明确的状态码与错误信息,如“员工不存在”、“工号已存在”、“指标不存在”等。 - 统一响应结构:API 返回统一的响应结构,包含状态码、消息、数据、分页信息等,便于前端展示与调试。 - 全局异常处理:注册 RequestValidationError 与 StarletteHTTPException 的处理器,记录错误日志并向上抛出,确保错误信息一致且可追踪。 **章节来源** - [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L60-L61) - [backend/app/api/v1/indicators.py](file://backend/app/api/v1/indicators.py#L66-L67) - [backend/app/api/v1/assessments.py](file://backend/app/api/v1/assessments.py#L99-L101) - [backend/app/main.py](file://backend/app/main.py#L58-L74) ### 验证规则扩展与自定义验证器 - 扩展 Pydantic 验证:可在现有 Field 参数基础上增加更多约束,如自定义正则表达式、长度范围、数值边界等;对于复杂字段(如 JSON),可使用 Json 类型与自定义解析器。 - 自定义验证器:可通过 Pydantic 的 field_validator 或 root_validator 实现跨字段验证与复杂业务规则;例如在创建考核时,验证明细中的指标权重与总分计算的一致性。 - 数据库约束增强:在模型层新增 CheckConstraint 或复合索引,以强化数据完整性;例如为“员工工号+部门”的唯一性约束添加复合索引。 - 业务规则扩展:在服务层增加新的业务规则检查点,如在创建考核时检查指标是否适用于当前科室类型、是否启用等。 **章节来源** - [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L153-L192) - [backend/app/models/models.py](file://backend/app/models/models.py#L143-L146) - [backend/app/services/assessment_service.py](file://backend/app/services/assessment_service.py#L114-L151) ## 依赖关系分析 - 版本要求:项目使用 FastAPI、SQLAlchemy、Pydantic 等核心依赖,版本在 requirements.txt 中声明,确保验证与 ORM 功能的稳定性。 - 模块间耦合:API 层依赖 Pydantic 模式与服务层;服务层依赖 SQLAlchemy 模型;模型层依赖数据库驱动与 Alembic 迁移工具。 - 异常处理:全局异常处理器统一处理验证与业务异常,减少重复代码并提升用户体验。 ```mermaid graph LR Req["requirements.txt"] --> FastAPI["FastAPI"] Req --> SQLAlchemy["SQLAlchemy"] Req --> Pydantic["Pydantic"] API["API 路由"] --> PydanticSchema["Pydantic 模式"] API --> Service["服务层"] Service --> Model["SQLAlchemy 模型"] Model --> DB["数据库"] Main["main.py"] --> API Main --> Service Main --> Model ``` **图表来源** - [backend/requirements.txt](file://backend/requirements.txt#L1-L16) - [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L10-L15) - [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py#L9-L10) - [backend/app/models/models.py](file://backend/app/models/models.py#L13-L13) - [backend/app/main.py](file://backend/app/main.py#L50-L77) **章节来源** - [backend/requirements.txt](file://backend/requirements.txt#L1-L16) - [backend/app/main.py](file://backend/app/main.py#L50-L77) ## 性能考虑 - 索引优化:为高频查询字段(如科室类型、状态、年月组合)建立索引,降低查询成本。 - 数值精度:使用 Numeric 类型存储金额与分数,避免浮点误差;合理设置精度与小数位数。 - 查询优化:在服务层使用 selectinload 等策略预加载关联对象,减少 N+1 查询问题。 - 异步 I/O:利用 SQLAlchemy 异步引擎与 FastAPI 的异步特性,提升并发处理能力。 ## 故障排除指南 - Pydantic 验证失败:检查请求体字段类型、长度与范围是否符合模式定义;查看响应中的错误字段与原因。 - 业务规则失败:确认业务状态是否允许当前操作(如仅草稿或已驳回状态可更新);检查唯一性约束冲突(如工号、指标编码)。 - 数据库约束失败:检查 CheckConstraint 与索引是否满足;确认外键关系是否正确。 - 异常处理:查看全局异常处理器的日志输出,定位具体错误位置与堆栈信息。 **章节来源** - [backend/app/main.py](file://backend/app/main.py#L58-L74) - [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L75-L78) - [backend/app/models/models.py](file://backend/app/models/models.py#L143-L146) ## 结论 本系统通过“Pydantic 模式验证 + SQLAlchemy 数据库约束 + 服务层业务规则”的三层验证机制,确保了数据在进入业务流程前后的完整性与一致性。API 层负责输入验证与业务规则检查,服务层负责复杂业务逻辑与数据一致性,模型层负责数据结构与约束定义。配合统一的异常处理与日志记录,系统在保证功能正确的同时,也具备良好的可维护性与可扩展性。未来可在 Pydantic 中引入自定义验证器与复杂字段解析,在模型层增加更多数据库约束,并在服务层扩展业务规则检查点,进一步完善验证体系。