Python Pydantic數(shù)據(jù)驗(yàn)證的實(shí)現(xiàn)
1. 什么是 Pydantic?
Pydantic 是一個功能強(qiáng)大的 Python 數(shù)據(jù)驗(yàn)證庫,它通過 Python 類型注解實(shí)現(xiàn)快速的數(shù)據(jù)驗(yàn)證和轉(zhuǎn)換。它不僅提供了全面的類型驗(yàn)證、自動數(shù)據(jù)轉(zhuǎn)換和詳細(xì)的錯誤處理機(jī)制,還具有基于 Rust 實(shí)現(xiàn)的高性能核心驗(yàn)證器。憑借其優(yōu)秀的 IDE 支持和可擴(kuò)展性,Pydantic 在 FastAPI 等 Web 框架、配置管理、數(shù)據(jù)序列化以及 API 接口模型定義等多個場景中得到廣泛應(yīng)用。
2. 安裝
pip install pydantic pip install pydantic-settings
3. 基礎(chǔ)使用
在開始使用 Pydantic 之前,我們需要了解它的核心概念和基本用法。Pydantic 的核心是通過定義模型類來實(shí)現(xiàn)數(shù)據(jù)驗(yàn)證,這些模型類繼承自 BaseModel。
3.1 創(chuàng)建基礎(chǔ)模型
基礎(chǔ)模型是 Pydantic 中最常用的功能。通過繼承 BaseModel 類,我們可以定義數(shù)據(jù)結(jié)構(gòu)和類型約束。每個字段都可以使用 Python 的類型注解來指定其類型,這些類型會在數(shù)據(jù)驗(yàn)證時被強(qiáng)制執(zhí)行。
from pydantic import BaseModel
from typing import Optional
from datetime import datetime
class User(BaseModel):
id: int
username: str
email: str
full_name: Optional[str] = None # 可選字段
created_at: datetime = datetime.now() # 默認(rèn)值
# 創(chuàng)建實(shí)例
user = User(
id=1,
username="john_doe",
email="john@example.com"
)
# 訪問數(shù)據(jù)
print(user.username) # 輸出: john_doe
# 轉(zhuǎn)換為字典
user_dict = user.model_dump()
字段定義說明:
- id: int - 必填的整數(shù)字段
- username: str - 必填的字符串字段
- email: str - 必填的郵箱字段
- full_name: Optional[str] - 可選的字符串字段,可以為 None
- created_at: datetime - 帶默認(rèn)值的日期時間字段
3.2 數(shù)據(jù)驗(yàn)證
Pydantic 的數(shù)據(jù)驗(yàn)證是自動進(jìn)行的,當(dāng)創(chuàng)建模型實(shí)例時,輸入數(shù)據(jù)會自動根據(jù)定義的類型進(jìn)行驗(yàn)證和轉(zhuǎn)換。如果驗(yàn)證失敗,Pydantic 會拋出詳細(xì)的 ValidationError 異常。
from pydantic import BaseModel, EmailStr, ValidationError
class UserRegistration(BaseModel):
username: str
email: EmailStr
age: int
try:
# 嘗試創(chuàng)建無效數(shù)據(jù)
user = UserRegistration(
username="john",
email="invalid-email", # 無效郵箱
age="not_a_number" # 無效年齡
)
except ValidationError as e:
print("驗(yàn)證錯誤:")
for error in e.errors():
print(f"- {error['loc'][0]}: {error['msg']}")
當(dāng)驗(yàn)證失敗時,錯誤信息會包含:
- 具體是哪個字段驗(yàn)證失敗
- 失敗的原因
- 期望的數(shù)據(jù)類型
- 實(shí)際接收到的數(shù)據(jù)類型
3.3 嵌套模型
在實(shí)際應(yīng)用中,數(shù)據(jù)結(jié)構(gòu)往往是嵌套的。Pydantic 完全支持模型嵌套,這使得我們可以構(gòu)建復(fù)雜的數(shù)據(jù)結(jié)構(gòu),同時保持?jǐn)?shù)據(jù)驗(yàn)證的嚴(yán)謹(jǐn)性。
from typing import List
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
addresses: List[Address]
# 使用嵌套模型
user = User(
name="John Doe",
addresses=[
{"street": "123 Main St", "city": "Boston", "country": "USA"},
{"street": "456 Park Ave", "city": "New York", "country": "USA"}
]
)
嵌套模型的優(yōu)勢:
- 保持?jǐn)?shù)據(jù)結(jié)構(gòu)的層次清晰
- 支持復(fù)雜的數(shù)據(jù)驗(yàn)證邏輯
- 方便數(shù)據(jù)的序列化和反序列化
4. 常用驗(yàn)證規(guī)則
Pydantic 提供了豐富的驗(yàn)證規(guī)則,可以滿足各種復(fù)雜的數(shù)據(jù)驗(yàn)證需求。這些規(guī)則可以組合使用,構(gòu)建出強(qiáng)大的驗(yàn)證邏輯。
4.1 基礎(chǔ)驗(yàn)證規(guī)則
Field 類是 Pydantic 提供的字段定義工具,它允許我們?yōu)樽侄翁砑痈鞣N驗(yàn)證規(guī)則和元數(shù)據(jù)。通過 Field,我們可以定義字段的約束條件、默認(rèn)值和描述信息。
from pydantic import BaseModel, Field, EmailStr, HttpUrl, constr
class User(BaseModel):
# 字符串驗(yàn)證
name: str = Field(..., min_length=2, max_length=50) # 必填,長度2-50
username: str = Field(..., pattern="^[a-zA-Z0-9_-]+$") # 只允許字母、數(shù)字、下劃線和橫杠
# 數(shù)值驗(yàn)證
age: int = Field(..., ge=0, le=120) # 大于等于0,小于等于120
score: float = Field(..., gt=0, lt=100) # 大于0,小于100
# 特殊類型驗(yàn)證
email: EmailStr # 郵箱驗(yàn)證
website: HttpUrl # URL驗(yàn)證
# 可選字段
description: str | None = Field(None, max_length=1000) # 可選,最大長度1000
驗(yàn)證規(guī)則說明:
- min_length/max_length: 控制字符串長度
- pattern: 使用正則表達(dá)式驗(yàn)證字符串格式
- ge/le: 大于等于/小于等于
- gt/lt: 大于/小于
4.2 列表驗(yàn)證
from typing import List
class Order(BaseModel):
# 列表長度驗(yàn)證
items: List[str] = Field(..., min_items=1, max_items=10)
# 列表元素唯一性驗(yàn)證
tags: List[str] = Field(..., unique_items=True)
# 價格必須為正數(shù)的列表
prices: List[float] = Field(..., gt=0)
4.3 自定義驗(yàn)證器
from pydantic import BaseModel, model_validator, field_validator
from datetime import datetime
class Order(BaseModel):
order_id: str
created_at: datetime
total_amount: float
items_count: int
# 字段級驗(yàn)證器
@field_validator('order_id')
def validate_order_id(cls, v):
if not v.startswith('ORD-'):
return f'ORD-{v}'
return v
# 模型級驗(yàn)證器
@model_validator(mode='after')
def validate_total(self):
if self.total_amount <= 0 and self.items_count > 0:
raise ValueError('Total amount must be positive when items exist')
return self
4.4 條件驗(yàn)證
from typing import Optional
from pydantic import BaseModel, Field, model_validator
class Product(BaseModel):
name: str
price: float
discount: Optional[float] = None
final_price: Optional[float] = None
@model_validator(mode='after')
def calculate_final_price(self):
if self.discount is not None:
if not 0 <= self.discount <= 1:
raise ValueError('Discount must be between 0 and 1')
self.final_price = self.price * (1 - self.discount)
else:
self.final_price = self.price
return self
4.5 常用驗(yàn)證類型
from pydantic import BaseModel, Field, EmailStr, HttpUrl, conint, confloat, constr
class UserProfile(BaseModel):
# 受約束的字符串
username: constr(min_length=3, max_length=20, pattern="^[a-zA-Z0-9_]+$")
# 受約束的整數(shù)
age: conint(ge=0, le=120)
# 受約束的浮點(diǎn)數(shù)
height: confloat(ge=0, le=300)
# 枚舉選擇
status: str = Field(..., pattern="^(active|inactive|pending)$")
# 布爾值
is_active: bool = True
這些驗(yàn)證規(guī)則涵蓋了日常開發(fā)中最常見的數(shù)據(jù)驗(yàn)證場景。通過組合使用這些規(guī)則,可以構(gòu)建出復(fù)雜的數(shù)據(jù)驗(yàn)證邏輯。記住幾個要點(diǎn):
- Field(…) 中的 … 表示該字段必填
- 使用 Optional 或 | None 表示可選字段
- 驗(yàn)證器分為字段級 (field_validator) 和模型級 (model_validator)
- 可以組合多個驗(yàn)證規(guī)則
- 驗(yàn)證規(guī)則的順序: 先定義字段,再添加驗(yàn)證規(guī)則
- 驗(yàn)證規(guī)則的執(zhí)行順序: 先定義的規(guī)則先執(zhí)行
5. 實(shí)際應(yīng)用示例
5.1 API 請求驗(yàn)證
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: bool = False
@app.post("/items/")
async def create_item(item: Item):
return item
5.2 配置管理
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
database_url: str
api_key: str
debug: bool = False
model_config = SettingsConfigDict(env_file='.env')
# 從環(huán)境變量加載配置
settings = Settings()
6. 小技巧
6.1. 數(shù)據(jù)轉(zhuǎn)換:
# 字典轉(zhuǎn)模型
data = {"name": "John", "age": "25"} # 注意 age 是字符串
user = User.model_validate(data) # 推薦使用 model_validate 而不是 parse_obj
# 模型轉(zhuǎn) JSON
json_str = user.model_dump_json() # 推薦使用 model_dump_json 而不是 json()
# 模型轉(zhuǎn)字典
user_dict = user.model_dump() # 推薦使用 model_dump 而不是 dict()
# 模型轉(zhuǎn) JSON 字符串(帶縮進(jìn))
json_str = user.model_dump_json(indent=4)
# JSON 字符串轉(zhuǎn)模型
user = User.model_validate_json(json_str)
6.2 錯誤處理:
try:
user = User(name="John", age="invalid")
except ValidationError as e:
print("數(shù)據(jù)無效:", e)到此這篇關(guān)于Python Pydantic數(shù)據(jù)驗(yàn)證的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Python Pydantic數(shù)據(jù)驗(yàn)證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
pytest用例間參數(shù)傳遞的兩種實(shí)現(xiàn)方式示例
pytest提供了許多運(yùn)行命令以供定制化運(yùn)行某一類測試用例或者某個測試用例等,下面這篇文章主要給大家介紹了關(guān)于pytest用例間參數(shù)傳遞的兩種實(shí)現(xiàn)方式,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-12-12
使用Python的Dataframe取兩列時間值相差一年的所有行方法
今天小編就為大家分享一篇使用Python的Dataframe取兩列時間值相差一年的所有行方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-07-07
pytorch實(shí)現(xiàn)mnist數(shù)據(jù)集的圖像可視化及保存
今天小編就為大家分享一篇pytorch實(shí)現(xiàn)mnist數(shù)據(jù)集的圖像可視化及保存,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-01-01
Python實(shí)現(xiàn)備份文件實(shí)例
這篇文章主要介紹了Python實(shí)現(xiàn)備份文件的方法,可實(shí)現(xiàn)針對各類常見擴(kuò)展名的文件進(jìn)行備份的功能,需要的朋友可以參考下2014-09-09
Windows 下python3.8環(huán)境安裝教程圖文詳解
這篇文章主要介紹了Windows 下python3.8環(huán)境安裝教程圖文詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03

