之前寫過一篇〈pydantic 小筆記〉,這集繼續紀錄 pydantic 的其他特性,在此大部分應用場景都是 pydantic + FastAPI,誰叫他們這麼香呢。
pydantic Model 繼承
pydantic model 可以繼承,例如 User
被幾個子類繼承:
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
class UserCreate(User):
password: str
class UserRead(User):
pass
一旦繼承,子類也會有 User
的 name
和 age
屬性,以及子類本身特有的屬性,例如 UserCreate
就有 name
、age
、password
三個屬性。
這是 FastAPI 中的一種設計模式,不同的子類對應不同的情境,同時也避免了打錯字、多打字的問題。
例如對於建立用戶的請求,大概會長這樣:
@app.post(path='/user', response_model=UserRead)
def create_user(user: UserCreate)
# Create User logic
return user
受惠於 pydantic 的檢查機制,傳送到 create_user()
的請求必須是有密碼的,而回傳的訊息則是不帶帳號密碼的,這中間不需要我們手動把 password
屬性摘除,pydantic 會自動過濾掉不存在 UserRead
類的屬性,這樣的設計也符合一般建立用戶的邏輯。
此 Model 非彼 Model
pydantic 最大的問題是它也有所謂的 model 和 schema,當再把資料庫的概念摻進來就造成語意上的混亂。
不僅是語意上,程式碼看起來也會相當冗餘,以前面的 User 資源為例,除了有 pydantic model 的定義外,在 ORM 大概也要寫一份極其相似的「model」:
class User(Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=255)
age = fields.IntField()
password = fields.CharField(max_length=255)
這樣又回到了多打字、打錯字的老問題,於是各路人馬都看不下去,紛紛提出解決方案。
SQLModel
FastAPI 本家作者另外開發的 SQLModel,它的基類 SQLModel
同時是 pydantic 的 model,也是 SQLAlchemy 的 declarative_base()
所產生的 model,只要繼承並依照 SQLModel 的規則訂定屬性就可以同時搞定兩方面的 model。
class User(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
age: int
password: str
但 SQLModel 目前還在早期開發階段,文件不齊,沒有 migration 和 seeding 的說明,不太能夠用作生產力工具。
Tortoise ORM
Tortoise ORM 是異步 ORM,它並不專為 FastAPI 打造,但還是有提供一些整合工具。
它的思路是用一個 pydantic_model_creator()
函式從 Tortoise model 生出一個 pydantic model:
class Users(models.Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=255)
age = fields.IntField()
password = fields.CharField(max_length=255)
class PydanticMeta:
exclude = ["password"]
User_Pydantic = pydantic_model_creator(cls=Users, name="User")
UserIn_Pydantic = pydantic_model_creator(cls=Users, name="UserIn")
因為不是為 pydantic 或 FastAPI 量身打造的,看起來就沒那麼優雅了,但它發展較為成熟,也有確定的 migration 機制。
具體該選哪個,取決於心臟的大小,在我看來他們都是不夠好的 ORM,我輩開發者需要的是傻瓜 ORM,傻瓜 ORM 不需要命名資料表、不需要自己增設 id
、created_at
、updated_at
欄位,也不用指定那 max_length
,甚至不用管文字的長短、數字的大小,Rails 的 Active Record 就具備以上所有的傻瓜特性,而 Python 世界的傻瓜 ORM 叫 Masonite ORM,遺憾的是沒什麼人用,殘念。
本文转自: https://editor.leonh.space/2022/pydantic-model/
本站仅做收录,版权归原作者所有。