FastAPI密码验证自定义错误未生效,如何返回指定错误信息?
FastAPI自定义密码长度验证错误不生效的问题解决
问题描述
尝试用FastAPI实现登录认证,要求密码长度小于6时返回自定义错误信息,但实际返回的是Pydantic默认的验证错误。
实现代码
class AuthSchema(BaseModel): email: str password: constr(min_length=6) @validator("password") def validate_password(cls, value): if len(value) < 6: raise HTTPException(status_code=400, detail="Password must be at least 6 characters long") return value @router.post("/login", response_model=CustomResponse) async def login_user(user: AuthSchema, db: Session = Depends(db.get_session)): try: if not UserServices().verify_user_password(db, user.email, user.password): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid credentials" ) except Exception as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=str(e) ) token = token_services.create_access_token({ "id": user.id, "role": user.role }) return CustomResponse( message="User logged in successfully", data={ "token": token }, status=200 )
实际返回错误
{ "detail": [ { "type": "string_too_short", "loc": [ "body", "password" ], "msg": "String should have at least 6 characters", "input": "123", "ctx": { "min_length": 6 }, "url": "https://errors.pydantic.dev/2.6/v/string_too_short" } ] }
问题原因
- Pydantic验证优先级问题:你使用的
constr(min_length=6)是Pydantic内置的字段约束验证器,它会优先于自定义的@validator执行。当密码长度不足时,内置验证先触发并返回默认错误,自定义的验证逻辑根本不会被执行。 - 版本适配问题:Pydantic 2.x中,
@validator是兼容旧版本的装饰器,官方推荐使用新的@field_validator,但核心原因还是内置约束的优先级更高。
解决方法
方法一:移除内置约束,使用自定义字段验证器
直接去掉constr(min_length=6),改用Pydantic 2.x推荐的@field_validator实现自定义验证,确保逻辑完全由自己控制:
from pydantic import BaseModel, field_validator from fastapi import HTTPException class AuthSchema(BaseModel): email: str password: str @field_validator("password") def validate_password(cls, value): if len(value) < 6: raise HTTPException(status_code=400, detail="Password must be at least 6 characters long") return value
方法二:全局捕获Pydantic验证错误,统一自定义响应
如果需要保留内置约束(比如自动生成接口文档时的长度提示),可以通过FastAPI的异常处理器全局捕获ValidationError,将默认错误转换成自定义消息:
from fastapi import Request, status from fastapi.responses import JSONResponse from pydantic import ValidationError # 在你的FastAPI实例中添加异常处理器 @app.exception_handler(ValidationError) async def custom_validation_exception_handler(request: Request, exc: ValidationError): custom_detail = [] for err in exc.errors(): # 针对密码长度不足的错误替换消息 if err["type"] == "string_too_short" and err["loc"][-1] == "password": custom_detail.append({"msg": "Password must be at least 6 characters long"}) else: custom_detail.append({"msg": err["msg"]}) return JSONResponse( status_code=status.HTTP_400_BAD_REQUEST, content={"detail": custom_detail} )
方法三:使用Pydantic的自定义错误消息(保留内置约束)
在Pydantic 2.x中,可以通过Annotated结合StringConstraints来设置自定义错误消息,既保留内置验证,又替换默认提示:
from pydantic import BaseModel, StringConstraints from typing import Annotated class AuthSchema(BaseModel): email: str password: Annotated[str, StringConstraints( min_length=6, min_length_msg="Password must be at least 6 characters long" )]
内容的提问来源于stack exchange,提问作者ogz
相关产品推荐
相关产品推荐

