在Pydantic模型中使用FastAPI验证当前用户



我有一个问题,我很惊讶以前没有人问过它。问题是:如何在Pydantic BaseModel中对登录用户进行验证?这在Django中非常简单,我们可以将请求对象传递给序列化器,但我不知道如何在这里实现它。

我的观点:

@router.post("/train_models", summary="Train models", response_model=SuccessResponse)
def train_models(train: TrainModels, user: TokenData = Depends(get_current_user),):
# do some work here
return {'success': True}
我BaseModel

:

class TrainModels(BaseModel):
target_column: str
user_file_id: int
@root_validator()
def validate(cls, values):
return values

我想确保用户可以访问user_file_id,这是他的物品,他可以访问它,但是如何访问呢?我想我可以在我的视图中做这个检查,但我想看到我的代码清晰,所有的验证逻辑严格保持在验证器中。

也许有一些方法可以传递一些参数给root_validator并在那里进行检查。

我的观点是业务逻辑不属于您的pydantic模型(并且模型不应该从数据库中获取数据等),而应该是服务存储或检索实际对象的责任。

一个选项是让你的服务在保存时抛出错误:

class TrainModelsService:
def save_train_model(train: TrainModels, user: User):
user_file = self.user_file_service.get_for_user_id(train.user_file_id, user.id)
if not user_file:
raise InvalidUserFile
self.db_session.....

@router.post("/train_models", summary="Train models", response_model=SuccessResponse)
def train_models(train: TrainModels, 
user: TokenData = Depends(get_current_user),
train_service: TrainService = Depends(get_train_service)
):
try:
train_service.save_train_model(train)
except InvalidUserFile:
# or use an exception handler that does this for you instead of having it in your view.
raise HTTPException(status_code=400, detail="Invalid user file")
# do some work here
return {'success': True}

另一个选择是使用依赖层次结构,就像你对你的用户所做的那样:

def get_valid_train_model_for_user(train: TrainModels, 
user: TokenData = Depends(get_current_user),
user_file_service: UserFileService = Depends(get_user_file_service),
):
user_file = user_file_service.get_for_user_id(train.user_file_id, user.id)
if not user_file:
raise HTTPException(status_code=400, detail='Invalid user file given')
return train

@router.post("/train_models", summary="Train models", response_model=SuccessResponse)
def train_models(train: TrainModels = Depends(get_valid_train_model_for_user)):
# do some work here
return {'success': True}

我倾向于尽可能多地使用依赖层次结构来强制约束,因为它可以很容易地在视图之间组合依赖并以不同的方式重用这些依赖。