在构建RESTful API时,经常需要处理复杂的数据关系。FastAPI通过支持多个关联模型,使得定义这些关系变得简单直观。这种方法不仅提高了代码的可维护性,还增强了API的灵活性。通过使用Pydantic库,我们可以轻松定义数据模型及其关联,从而在FastAPI应用中实现强大的数据处理逻辑。无论是一对多、多对一还是多对多的关系,FastAPI都能游刃有余。掌握这一技巧,将帮助你构建更加健壮和高效的API。
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, EmailStr
from typing import Optional
# 创建 FastAPI 应用实例
api = FastAPI()
# 定义输入用户模型
class NewUser(BaseModel):
nickname: str # 用户名
secret: str # 密码
contact: EmailStr # 邮箱
real_name: Optional[str] = None # 真实姓名,可选
# 定义输出用户模型
class ExistingUser(BaseModel):
nickname: str # 用户名
contact: EmailStr # 邮箱
real_name: Optional[str] = None # 真实姓名,可选
# 定义数据库用户模型
class UserDB(BaseModel):
nickname: str # 用户名
secure_password: str # 加密密码
contact: EmailStr # 邮箱
real_name: Optional[str] = None # 真实姓名,可选
# 模拟密码加密函数
def mock_password_encrypter(plain_text: str) -> str: # 加密明文密码
"""加密明文密码"""
return "encrypted_" + plain_text
# 模拟保存用户到数据库的函数
def mock_user_storage(new_user: NewUser) -> UserDB: # 模拟保存用户到数据库
"""模拟将新用户保存到数据库"""
secure_password = mock_password_encrypter(new_user.secret)
user_db = UserDB(**new_user.dict(), secure_password=secure_password)
""" **new_user.dict()双星号函数 """
print("用户数据已存储!...虚拟的")
return user_db
# 创建用户端点
@api.post("/add_user/", response_model=ExistingUser)
async def add_new_user(new_user: NewUser) -> ExistingUser: # 创建新用户并返回用户信息
"""创建新用户并返回用户信息"""
try:
saved_user = mock_user_storage(new_user)
return saved_user
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) # 服务器内部错误
注解说明:
-
字段注解:在
NewUser
,ExistingUser
,UserDB
类的字段定义中,添加了注释来描述每个字段的含义。 -
函数参数和返回值注解:在
mock_password_encrypter
和mock_user_storage
函数定义中,添加了注释来描述函数的作用和返回值类型。 -
文档字符串:在每个函数和方法的开始处,添加了文档字符串(docstring),这些字符串详细描述了函数的作用和行为。
-
异常处理注解:在
add_new_user
函数中,添加了注释来描述异常处理逻辑。 -
双星号字典解包:
**new_user.dict()
- new_user.dict() 会将Pydantic模型的实例转换为一个普通的Python字典
- 双星号是一个特殊的语法符号,用于表示双星号字典解包操作。当使用在函数调用中时,它允许你将一个字典对象的所有键值对作为关键字参数传递给函数。
这些注解和文档字符串有助于提高代码的可读性和可维护性,同时也使得代码更加易于理解
解包 dict 和更多关键字
例如:
UserInDB(**user_in.dict(), hashed_password=hashed_password)
输出的结果如下:
UserInDB(
username = user_dict["username"],
password = user_dict["password"],
email = user_dict["email"],
full_name = user_dict["full_name"],
hashed_password = hashed_password,
)