In this unit, we will implement a demo program that includes many Pydantic models for specific use-cases:
The input model needs to be able to have a password.
The output model should not have a password.
The database model would probably need to store a hashed password.
Example program
from fastapi import FastAPIfrom pydantic import BaseModel, EmailStrapp =FastAPI()classUserIn(BaseModel): username:str password:str email: EmailStr full_name:str=NoneclassUserOut(BaseModel): username:str email: EmailStr full_name:str=NoneclassUserDB(BaseModel): username:str hashed_password:str email: EmailStr full_name:str=Nonedeffake_password_hasher(raw_password:str):"""This is a fake password hasher, don't use it in production."""return"salted_"+ raw_passworddeffake_save_user(user_in: UserIn): hashed_password =fake_password_hasher(user_in.password) user_db =UserDB(**user_in.model_dump(), hashed_password=hashed_password)print("User has been saved to an imaginary database!")return user_db@app.post("/user/", response_model=UserOut)asyncdefcreate_user(user: UserIn): user_saved =fake_save_user(user)return user_saved
Within function definitions, the double asterisk, **, is used in conjunction with the parameter name **kwargs (though kwargs itself is not mandatory). This allows you to accept a variable number of keyword arguments when the function is called.
Reduce code duplication
In the above program, there are code snippets duplicated across class definition. As code duplication increases the chances of bugs, security issues, code desynchronization issues (when you update in one place but not in the others), etc.
from fastapi import FastAPIfrom pydantic import BaseModel, EmailStrapp =FastAPI()classUserBase(BaseModel): username:str email: EmailStr full_name:str=NoneclassUserIn(UserBase): password:strclassUserOut(UserBase):passclassUserDB(UserBase): hashed_password:strdeffake_password_hasher(raw_password:str):"""This is a fake password hasher, don't use it in production."""return"salted_"+ raw_passworddeffake_save_user(user_in: UserIn): hashed_password =fake_password_hasher(user_in.password) user_db =UserDB(**user_in.model_dump(), hashed_password=hashed_password)print("User has been saved to an imaginary database!")return user_db@app.post("/user/", response_model=UserOut)asyncdefcreate_user(user: UserIn): user_saved =fake_save_user(user)return user_saved