Pydantic 是一个 Python 数据验证和设置管理库,它使用 Python 类型注解来验证数据。Pydantic 的核心功能是通过定义 Python 类,并利用类型注解来自动验证数据的类型和格式。它广泛用于 FastAPI 等框架中,用于请求数据的验证和序列化。
基本概念
-
模型(Model):Pydantic 的核心是
BaseModel
类,所有 Pydantic 模型都继承自它。 -
字段(Field):模型中的每个属性称为字段,可以指定字段的类型和默认值。
-
验证(Validation):Pydantic 会自动验证字段的类型和格式,如果数据不符合要求,会抛出
ValidationError
。 -
序列化(Serialization):Pydantic 可以将模型实例转换为字典或 JSON 格式。
安装 Pydantic
首先,确保安装了 Pydantic:
bash
复制
pip install pydantic
示例教程
1. 定义一个简单的模型
Python
复制
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str
email: str
is_active: bool = False # 默认值
# 创建一个 User 实例
user = User(id=1, name="John Doe", email="john.doe@example.com", is_active=True)
print(user)
# 输出:
# id=1 name='John Doe' email='john.doe@example.com' is_active=True
2. 数据验证
Pydantic 会自动验证字段的类型和格式。如果数据不符合要求,会抛出 ValidationError
。
Python
复制
try:
user = User(id="not_an_int", name="John Doe", email="john.doe@example.com")
except ValueError as e:
print(e)
# 输出:
# 1 validation error for User
# id
# value is not a valid integer (type=type_error.integer)
3. 使用默认值
字段可以有默认值,如果创建实例时未提供该字段的值,则使用默认值。
Python
复制
class User(BaseModel):
id: int
name: str
email: str
is_active: bool = False # 默认值
user = User(id=1, name="John Doe", email="john.doe@example.com")
print(user)
# 输出:
# id=1 name='John Doe' email='john.doe@example.com' is_active=False
4. 字段验证
可以为字段添加自定义验证逻辑。
Python
复制
from pydantic import BaseModel, ValidationError, validator
class User(BaseModel):
id: int
name: str
email: str
is_active: bool = False
@validator('email')
def email_must_contain_at(cls, v):
if '@' not in v:
raise ValueError('must contain an @')
return v
try:
user = User(id=1, name="John Doe", email="john.doeexample.com")
except ValidationError as e:
print(e)
# 输出:
# 1 validation error for User
# email
# must contain an @ (type=value_error)
5. 嵌套模型
Pydantic 支持嵌套模型,可以定义复杂的数据结构。
Python
复制
class Address(BaseModel):
street: str
city: str
zip_code: str
class User(BaseModel):
id: int
name: str
email: str
address: Address
user = User(
id=1,
name="John Doe",
email="john.doe@example.com",
address=Address(street="123 Main St", city="Anytown", zip_code="12345")
)
print(user)
# 输出:
# id=1 name='John Doe' email='john.doe@example.com' address=Address(street='123 Main St', city='Anytown', zip_code='12345')
6. 序列化
Pydantic 模型可以轻松转换为字典或 JSON 格式。
Python
复制
user_dict = user.dict()
print(user_dict)
# 输出:
# {'id': 1, 'name': 'John Doe', 'email': 'john.doe@example.com', 'address': {'street': '123 Main St', 'city': 'Anytown', 'zip_code': '12345'}}
user_json = user.json()
print(user_json)
# 输出:
# {"id": 1, "name": "John Doe", "email": "john.doe@example.com", "address": {"street": "123 Main St", "city": "Anytown", "zip_code": "12345"}}
7. 配置类
可以通过定义 Config
类来自定义模型的行为。
Python
复制
class User(BaseModel):
id: int
name: str
email: str
class Config:
extra = 'forbid' # 禁止额外字段
try:
user = User(id=1, name="John Doe", email="john.doe@example.com", extra_field="not allowed")
except ValidationError as e:
print(e)
# 输出:
# 1 validation error for User
# extra_field
# extra fields not permitted (type=value_error.extra)
总结
Pydantic 是一个强大的工具,用于数据验证和设置管理。通过定义模型和字段,Pydantic 可以自动验证数据的类型和格式,并提供序列化功能。它广泛用于 FastAPI 等框架中,用于处理请求数据的验证和响应数据的序列化。
pydantic + mongodb
搜索 Pydantic MongoDB 数据验证
以下是结合 Pydantic 和 MongoDB 的使用教程,包括数据验证、模型定义、以及与 FastAPI 的集成示例:
1. 环境准备与依赖安装
确保安装了以下依赖:
bash
复制
pip install fastapi uvicorn motor pydantic pymongo
这些包分别用于 FastAPI 框架、异步 MongoDB 驱动、数据验证和 MongoDB 官方驱动。
2. 定义 Pydantic 模型
使用 Pydantic 的 BaseModel
定义数据模型,同时处理 MongoDB 自动生成的 _id
字段:
Python
复制
from pydantic import BaseModel, Field
from bson import ObjectId
from typing import Optional
class PyObjectId(ObjectId):
@classmethod
def __get_validators__(cls):
yield cls.validate
@classmethod
def validate(cls, v):
if not ObjectId.is_valid(v):
raise ValueError("Invalid ObjectId")
return ObjectId(v)
@classmethod
def __modify_schema__(cls, field_schema):
field_schema.update(type="string")
class User(BaseModel):
id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")
name: str
email: str
is_active: Optional[bool] = False
class Config:
allow_population_by_field_name = True
json_encoders = {ObjectId: str}
在上述代码中,PyObjectId
是一个自定义的 Pydantic 类型,用于处理 MongoDB 的 _id
字段。
3. 配置 MongoDB 连接
使用 motor
配置异步 MongoDB 客户端:
Python
复制
from motor.motor_asyncio import AsyncIOMotorClient
from fastapi import FastAPI
app = FastAPI()
@app.on_event("startup")
async def startup_db_client():
app.mongodb_client = AsyncIOMotorClient("mongodb://localhost:27017")
app.mongodb = app.mongodb_client["your_database_name"]
@app.on_event("shutdown")
async def shutdown_db_client():
app.mongodb_client.close()
4. 实现 CRUD 操作
以下是创建、读取、更新和删除操作的示例:
Python
复制
from fastapi import HTTPException
# 创建用户
@app.post("/users/", response_model=User)
async def create_user(user: User):
user_dict = user.dict(by_alias=True)
await app.mongodb["users"].insert_one(user_dict)
return user
# 获取用户
@app.get("/users/{user_id}", response_model=User)
async def get_user(user_id: str):
user = await app.mongodb["users"].find_one({"_id": ObjectId(user_id)})
if not user:
raise HTTPException(status_code=404, detail="User not found")
return user
# 更新用户
@app.put("/users/{user_id}", response_model=User)
async def update_user(user_id: str, user: User):
await app.mongodb["users"].update_one(
{"_id": ObjectId(user_id)}, {"$set": user.dict(exclude_unset=True)}
)
return await get_user(user_id)
# 删除用户
@app.delete("/users/{user_id}")
async def delete_user(user_id: str):
result = await app.mongodb["users"].delete_one({"_id": ObjectId(user_id)})
if not result.deleted_count:
raise HTTPException(status_code=404, detail="User not found")
return {"message": "User deleted successfully"}
5. 启动 FastAPI 应用
运行以下命令启动 FastAPI 应用:
bash
复制
uvicorn your_module_name:app --reload
将 your_module_name
替换为包含上述代码的 Python 文件名。
注意事项
-
在 Pydantic 模型中,通过
Field
和alias
参数处理 MongoDB 的_id
字段。 -
使用
motor
来实现异步数据库操作。 -
通过
Config
类的json_encoders
配置,确保ObjectId
在序列化时被正确处理。
通过上述步骤,你可以实现一个基于 Pydantic 和 MongoDB 的数据验证和存储系统,并与 FastAPI 集成以构建 RESTful API。
复制
分享
bson 基本教程和例子
搜索 bson 基本教程
BSON 基本教程和使用示例
BSON(Binary JSON)是一种二进制格式的 JSON 数据,广泛用于 MongoDB 数据库中。它支持所有 JSON 数据结构类型,并增加了对日期、不同大小的整数、ObjectId 和二进制数据等类型的支持。以下是一些基本的 BSON 操作和使用示例:
1. BSON 的基本操作
1.1 创建 BSON 文档
在 Python 中,可以使用 bson
模块来创建和操作 BSON 数据。以下是一个创建 BSON 文档的示例:
Python
复制
import bson
# 创建一个 BSON 文档
data = {
"name": "Alice",
"age": 25,
"address": {
"city": "Beijing",
"country": "China"
},
"scores": [
{"name": "english", "grade": 99},
{"name": "chinese", "grade": 100}
]
}
# 编码为 BSON 格式
encoded_data = bson.BSON.encode(data)
print("Encoded BSON data:", encoded_data)
# 解码 BSON 数据
decoded_data = bson.BSON.decode(encoded_data)
print("Decoded BSON data:", decoded_data)
1.2 BSON 数据类型
BSON 支持多种数据类型,包括:
-
字符串
-
整数
-
浮点数
-
布尔值
-
日期
-
ObjectId
-
二进制数据
-
嵌套文档和数组
2. 在 MongoDB 中使用 BSON
2.1 查询操作
使用 bson
模块可以构建查询条件。以下是一些常见的查询操作示例:
Python
复制
from pymongo import MongoClient
import bson
# 连接到 MongoDB
client = MongoClient("mongodb://localhost:27017")
db = client["your_database"]
collection = db["your_collection"]
# 查询所有文档
results = collection.find({})
for result in results:
print(result)
# 根据 ObjectId 查询
object_id = bson.ObjectId("5204af979955496907000001")
result = collection.find_one({"_id": object_id})
print(result)
# 单条件查询
results = collection.find({"name": "Alice"})
for result in results:
print(result)
2.2 更新操作
更新操作可以通过 $set
等操作符完成:
Python
复制
# 更新字段值
collection.update_one(
{"_id": object_id},
{"$set": {"name": "Bob", "age": 30}}
)
# 向数组中添加元素
collection.update_one(
{"_id": object_id},
{"$push": {"scores": {"name": "math", "grade": 95}}}
)
2.3 删除操作
删除操作可以通过 remove
方法完成:
Python
复制
# 删除文档
collection.remove({"name": "Alice"})
3. BSON 的高级用法
3.1 有序和无序文档
在 Python 中,可以使用 bson.D
和 bson.M
来创建有序和无序的 BSON 文档:
Python
复制
from bson import D, M
# 有序文档
ordered_doc = D([("name", "Alice"), ("age", 25)])
print("Ordered document:", ordered_doc)
# 无序文档
unordered_doc = M({"name": "Alice", "age": 25})
print("Unordered document:", unordered_doc)
3.2 BSON 数组
BSON 数组可以通过 bson.A
创建:
Python
复制
from bson import A
# 创建 BSON 数组
array = A(["apple", "banana", "cherry"])
print("BSON array:", array)
4. 总结
BSON 是一种高效的二进制 JSON 格式,广泛用于 MongoDB 数据库中。通过 bson
模块,可以在 Python 中轻松创建、编码和解码 BSON 数据。同时,BSON 也支持多种数据类型和复杂的文档结构,能够满足各种数据存储和查询需求。
复制
分享
ObjectId
在 MongoDB 中,ObjectId
是一种特殊的唯一标识符,用于唯一标识集合中的每个文档。ObjectId
是由 12 字节(96 位)的二进制数据组成,通常以 24 位的十六进制字符串表示。
ObjectId 的结构
ObjectId
的 12 字节数据由以下部分组成:
-
时间戳(4 字节):表示 ObjectId 创建时的 Unix 时间戳(自 1970 年 1 月 1 日以来的秒数)。
-
机器标识(3 字节):用于区分不同机器生成的 ObjectId。
-
进程标识(2 字节):用于区分同一机器上的不同进程。
-
计数器(3 字节):用于确保在同一秒内生成的 ObjectId 也是唯一的。
ObjectId 的优点
-
唯一性:
ObjectId
能够在分布式系统中生成全局唯一的标识符。 -
时间排序:由于 ObjectId 的前 4 字节是时间戳,因此可以根据 ObjectId 排序来获取文档的创建顺序。
-
自动生成:MongoDB 驱动程序通常会自动为新文档生成
ObjectId
。
在 Python 中使用 ObjectId
在 Python 中,可以使用 bson
模块或 pymongo
模块来操作 ObjectId
。
1. 安装依赖
确保安装了 pymongo
和 bson
:
bash
复制
pip install pymongo bson
2. 创建 ObjectId
Python
复制
from bson import ObjectId
# 创建一个新的 ObjectId
obj_id = ObjectId()
print("Generated ObjectId:", obj_id)
# ObjectId 是一个二进制对象,可以转换为字符串
obj_id_str = str(obj_id)
print("ObjectId as string:", obj_id_str)
3. 从字符串创建 ObjectId
Python
复制
from bson import ObjectId
# 从字符串创建 ObjectId
obj_id_str = "5f44468b9b7e4a8f4f8f4f8f"
obj_id = ObjectId(obj_id_str)
print("ObjectId from string:", obj_id)
4. 获取 ObjectId 的时间戳
Python
复制
from bson import ObjectId
from datetime import datetime
# 创建一个新的 ObjectId
obj_id = ObjectId()
# 获取 ObjectId 的时间戳
timestamp = obj_id.generation_time
print("ObjectId timestamp:", timestamp)
# 将时间戳转换为 Python 的 datetime 对象
print("ObjectId datetime:", datetime.fromtimestamp(timestamp.timestamp()))
5. 在 MongoDB 中使用 ObjectId
在与 MongoDB 交互时,ObjectId
通常用于指定文档的 _id
字段。
Python
复制
from pymongo import MongoClient
from bson import ObjectId
# 连接到 MongoDB
client = MongoClient("mongodb://localhost:27017")
db = client["your_database"]
collection = db["your_collection"]
# 插入文档
document = {"name": "Alice", "age": 25}
result = collection.insert_one(document)
print("Inserted document ID:", result.inserted_id)
# 查询文档
obj_id = result.inserted_id
document = collection.find_one({"_id": obj_id})
print("Retrieved document:", document)
注意事项
-
唯一性:虽然
ObjectId
是设计为全局唯一的,但在极端情况下(如短时间内高并发生成)可能会出现冲突。建议在实际应用中进行唯一性检查。 -
时间排序:虽然 ObjectId 的时间戳部分可以用于排序,但仅依赖 ObjectId 的时间戳进行排序可能不够精确,建议结合其他字段(如
created_at
)进行排序。 -
兼容性:
ObjectId
是 MongoDB 特有的标识符,如果需要与其他数据库或系统集成,可能需要额外处理。
通过以上方法,你可以在 Python 中生成、解析和使用 ObjectId
,并将其应用于 MongoDB 数据库操作中。
复制