FastAPI+SQLModel中name字段非空验证失效问题求助
问题原因及解决办法
核心问题:验证器装饰器版本不兼容
你使用的@validator是Pydantic v1的语法,而当前SQLModel默认依赖Pydantic v2,该装饰器在v2中已被弃用,需改用@field_validator才能生效。
修复步骤
导入正确的验证器装饰器
从pydantic模块导入field_validator:from pydantic import field_validator替换验证器装饰器并优化逻辑
将原@validator('name')替换为@field_validator('name'),并添加mode='before'参数确保在数据类型转换前执行验证,拦截全空格的空字符串:@field_validator('name', mode='before') def name_must_not_be_empty(cls, v): if not v or v.strip() == '': raise ValueError('Name cannot be empty or just whitespace') return v.strip() # 可选:自动去除首尾空格,存储干净数据补充字段约束逻辑
原Field(..., min_length=1)仅限制字符串长度≥1,无法识别全空格的空字符串,结合验证器可实现更全面的校验。另外注意:nullable=False是控制数据库字段是否可为空,与Pydantic的输入数据验证作用不同。
完整修正后的代码片段
from datetime import datetime from typing import Optional from sqlmodel import SQLModel, Field, Session, create_engine, Depends from fastapi import FastAPI, HTTPException from pydantic import field_validator app = FastAPI() # 数据库连接示例 engine = create_engine("sqlite:///./test.db") SQLModel.metadata.create_all(engine) def get_session(): with Session(engine) as session: yield session # 用户表模型 class UserBase(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) name: str = Field(..., min_length=1, nullable=False) email: str = Field(min_length=1, default=None, unique=True) password: str = Field(min_length=1) date_created: datetime = Field(default=datetime.now(), nullable=False) @field_validator('name', mode='before') def name_must_not_be_empty(cls, v): if not v or v.strip() == '': raise ValueError('Name cannot be empty or just whitespace') return v.strip() # 创建用户响应模型 class CreateUser(SQLModel): message: str = 'Successfully created user' id: int name: str email: str # 创建用户接口 @app.post('/users/', response_model=CreateUser) def create_user(user: UserBase, session: Session = Depends(get_session)): # 检查邮箱是否已存在 existing_user = session.query(UserBase).filter(UserBase.email == user.email).first() if existing_user: raise HTTPException(status_code=400, detail="Email already registered") session.add(user) session.commit() session.refresh(user) # 刷新获取数据库生成的ID return {"message": "Successfully created user", "id": user.id, "name": user.name, "email": user.email}
额外说明
mode='before'确保验证器在Pydantic类型转换前执行,避免空字符串因类型转换绕过验证。session.refresh(user)用于获取数据库自动生成的id值,避免返回None。
内容的提问来源于stack exchange,提问作者Kons
相关产品推荐
相关产品推荐

