Become a sponsor

参数验证
使用 Pydantic v2 进行请求参数验证。所有请求体参数通过 Pydantic BaseModel 定义,FastAPI 自动解析和验证 JSON 请求体,验证失败返回标准格式错误信息。BaseForm 基类位于 src/core/base_schemas.py。
# src/modules/system/position/schemas.py
# +======================================================================
# | 模块: 岗位表单验证
# | 说明: 岗位创建/编辑/状态更新的请求数据校验
# +======================================================================
from typing import Optional
from pydantic import BaseModel, Field
from core.base_schemas import BaseForm
# ============================================================
# 岗位表单类
# ============================================================
class PositionForm(BaseForm):
"""岗位创建/编辑表单"""
name: str = Field(..., min_length=1, max_length=150, description="岗位名称")
status: int = Field(..., ge=1, le=2, description="岗位状态:1-在用 2-停用")
sort: int = Field(..., ge=0, le=99999, description="岗位排序")
# ============================================================
# 设置状态表单类
# ============================================================
class PositionStatusForm(BaseModel):
"""岗位状态更新表单"""
id: int = Field(..., gt=0, description="岗位ID")
status: int = Field(..., ge=1, le=2, description="岗位状态:1-在用 2-停用")@router.post('/add')
@permission_required("sys:position:add")
@check_demo
async def add(request: Request, data: PositionForm):
return await position.PositionAdd(request, data)自动验证
FastAPI 在调用端点函数前自动完成参数验证。验证失败时返回标准格式错误:
{"code": 1, "data": null, "msg": "name: 字段长度不能少于1个字符"}Pydantic v2 提供丰富的字段约束:
| 约束 | 说明 | 示例 |
|---|---|---|
min_length | 字符串最小长度 | Field(..., min_length=1) |
max_length | 字符串最大长度 | Field(..., max_length=150) |
ge | 大于等于 | Field(..., ge=0) |
le | 小于等于 | Field(..., le=99999) |
gt | 大于 | Field(..., gt=0) |
lt | 小于 | Field(..., lt=100) |
pattern | 正则匹配 | Field(..., pattern=r'^[a-z]+$') |
使用 @field_validator 装饰器添加自定义验证逻辑:
from pydantic import BaseModel, Field, field_validator
class UserForm(BaseForm):
username: str = Field(..., min_length=1, max_length=50)
email: str = Field(..., max_length=100)
@field_validator('username')
@classmethod
def validate_username(cls, v):
if not v.isalnum():
raise ValueError('用户名只能包含字母和数字')
return v
@field_validator('email')
@classmethod
def validate_email(cls, v):
if '@' not in v:
raise ValueError('邮箱格式不正确')
return v所有创建/编辑表单应继承 BaseForm,自动获得 id 字段和空字符串处理:
# src/core/base_schemas.py
# +======================================================================
# | 模块: 表单基类
# | 说明: 统一处理前端传入的空字符串 id → None 等通用校验
# +======================================================================
"""表单基类:统一处理前端传入的空字符串 id → None 等通用校验。"""
from typing import Optional
from pydantic import BaseModel, Field, field_validator
# ============================================================
# 表单基类
# ============================================================
class BaseForm(BaseModel):
"""
表单基类
所有创建/编辑表单应继承此类,自动获得:
1. id 字段:Optional[int],前端传空字符串时自动转为 None
"""
id: Optional[int] = Field(None, description="主键ID")
@field_validator('id', mode='before')
@classmethod
def empty_str_to_none(cls, v):
"""前端 POST 空字符串 '' 时转为 None,避免 Pydantic 整数解析报错"""
if v == '' or v == 'null' or v == 'undefined':
return None
return v前端空字符串
前端某些组件(如 el-select)在未选择时可能传空字符串 "",BaseForm 的 empty_str_to_none 验证器会自动将其转为 None,避免整数字段解析报错。
在 Pydantic 验证器中查询数据库校验唯一性:
from pydantic import field_validator
from core.database import get_db_session
from modules.system.position.models import Position
class PositionForm(BaseForm):
name: str = Field(..., min_length=1, max_length=150)
@field_validator('name')
@classmethod
def check_unique_name(cls, v, info):
db = get_db_session()
exclude_id = info.data.get('id')
query = db.query(Position).filter(
Position.name == v,
Position.is_delete == 0
)
if exclude_id:
query = query.filter(Position.id != exclude_id)
if query.first():
raise ValueError('岗位名称已存在')
return v# src/modules/auth/schemas.py
# +======================================================================
# | 模块: 登录表单验证
# | 说明: 用户登录的请求数据校验
# +======================================================================
from pydantic import BaseModel, Field
from core.config import CAPTCHA_LENGTH
# ============================================================
# 登录表单类
# ============================================================
class LoginForm(BaseModel):
"""登录表单验证类"""
username: str = Field(..., min_length=1, max_length=20, description="登录账号")
password: str = Field(..., min_length=6, max_length=128, description="登录密码")
code: str = Field(..., min_length=CAPTCHA_LENGTH, max_length=CAPTCHA_LENGTH, description="验证码")
key: str = Field(..., min_length=1, description="KEY值")验证失败时,全局异常处理器捕获 RequestValidationError 并返回标准格式:
{
"code": 1,
"data": null,
"msg": "name: 字段长度不能少于1个字符/status: 输入值必须大于等于1",
"ok": false
}多个错误用 / 分隔。
参数验证模块具备以下特点:
1. Pydantic v2:类型安全、自动解析 JSON 请求体
2. 丰富约束:min_length、max_length、ge、le、gt、lt、pattern
3. 自定义验证:@field_validator 实现复杂校验逻辑
4. BaseForm 基类:统一 id 字段处理,兼容前端空字符串
5. 唯一性校验:验证器中查询数据库,确保字段唯一性
6. 标准错误:全局异常处理器统一错误响应格式