1. 程式人生 > 其它 >FastAPI(21)- 多個模型的程式碼演進

FastAPI(21)- 多個模型的程式碼演進

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

Pydantic 入門篇

**user.dict()

先將 user 轉成 dict,然後解包

Python解包教程

減少程式碼重複

核心思想

  • 減少程式碼重複是 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)