FastAPI(21)- 多個模型的程式碼演進
阿新 • • 發佈:2022-01-05
FastAPI(21)- 多個模型的程式碼演進
前言
在一個完整的應用程式中,通常會有很多個相關模型,比如
- 請求模型需要有 password
- 響應模型不應該有 password
- 資料庫模型可能需要一個 hash 加密過的 password
多個模型的栗子
需求
- 註冊功能
- 請求輸入密碼
- 響應不需要輸出密碼
- 資料庫儲存加密後的密碼
實際程式碼
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
# author: 小菠蘿測試筆記
# blog: https://www.cnblogs.com/poloyy/
# time: 2021/9/22 8:28 上午
# file: 19_extra models.py
"""
import uvicorn
from fastapi import FastAPI
from typing import Optional
from pydantic import BaseModel, EmailStr
app = FastAPI()
# 請求模型
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: Optional[str] = None
# 響應模型
class UserOut(BaseModel):
username: str
email: EmailStr
full_name: Optional[str] = None
# 資料庫模型
class UserInDB(BaseModel):
username: str
hashed_password: str
email: EmailStr
full_name: Optional[str] = None
# 加密演算法
def fake_password_hasher(password: str) -> str:
return "supersecret" + password
# 資料庫儲存
def fake_save_user(user: UserIn):
# 取出使用者的密碼進行加密
hash_password = fake_password_hasher(user.password)
# 轉換為資料庫模型
userInDB = UserInDB(**user.dict(), hashed_password=hash_password)
# 返回資料
return userInDB
@app.post("/user", response_model=UserOut)
async def create_user(user: UserIn):
# 建立使用者,落庫
user_saved = fake_save_user(user)
# 返回儲存後的使用者資訊
return user_saved
if __name__ == "__main__":
uvicorn.run(app="19_extra_models:app", host="127.0.0.1", port=8080, reload=True, debug=True)
.dict()
是 Pydantic 提供的方法,將模型的例項物件轉換為 dict
**user.dict()
先將 user 轉成 dict,然後解包
減少程式碼重複
核心思想
- 減少程式碼重複是 FastAPI 的核心思想之一。
- 因為程式碼重複增加了錯誤、安全問題、程式碼同步問題(當在一個地方更新而不是在其他地方更新時)等的可能性
上面程式碼存在的問題
三個模型都共享大量資料
利用 Python 繼承的思想進行改造
- 宣告一個 UserBase 模型,作為其他模型的基礎
- 然後建立該模型的子類來繼承其屬性(型別宣告、驗證等),所有資料轉換、驗證、文件等仍然能正常使用
- 這樣,不同模型之間的差異(使用明文密碼、使用雜湊密碼、不使用密碼)也很容易識別出來
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
# author: 小菠蘿測試筆記
# blog: https://www.cnblogs.com/poloyy/
# time: 2021/9/22 8:28 上午
# file: 19_extra models.py
"""
import uvicorn
from fastapi import FastAPI
from typing import Optional
from pydantic import BaseModel, EmailStr
app = FastAPI()
# 基類模型
class UserBase(BaseModel):
username: str
email: EmailStr
full_name: Optional[str] = None
# 請求模型
class UserIn(UserBase):
password: str
# 響應模型
class UserOut(UserBase):
pass
# 資料庫模型
class UserInDB(UserBase):
hashed_password: str
# 加密演算法
def fake_password_hasher(password: str) -> str:
return "supersecret" + password
# 資料庫儲存
def fake_save_user(user: UserIn):
# 取出使用者的密碼進行加密
hash_password = fake_password_hasher(user.password)
# 轉換為資料庫模型
userInDB = UserInDB(**user.dict(), hashed_password=hash_password)
# 返回資料
return userInDB
@app.post("/user", response_model=UserOut)
async def create_user(user: UserIn):
# 建立使用者,落庫
user_saved = fake_save_user(user)
# 返回儲存後的使用者資訊
return user_saved
if __name__ == "__main__":
uvicorn.run(app="19_extra models:app", host="127.0.0.1", port=8080, reload=True, debug=True)