Pydantic Python 数据验证和设置管理库

Avatar

Pydantic 是一个 Python 数据验证和设置管理库,它使用 Python 类型注解来验证数据。Pydantic 的核心功能是通过定义 Python 类,并利用类型注解来自动验证数据的类型和格式。它广泛用于 FastAPI 等框架中,用于请求数据的验证和序列化。

基本概念

  1. 模型(Model):Pydantic 的核心是 BaseModel 类,所有 Pydantic 模型都继承自它。

  2. 字段(Field):模型中的每个属性称为字段,可以指定字段的类型和默认值。

  3. 验证(Validation):Pydantic 会自动验证字段的类型和格式,如果数据不符合要求,会抛出 ValidationError

  4. 序列化(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 模型中,通过 Fieldalias 参数处理 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.Dbson.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 字节数据由以下部分组成:

  1. 时间戳(4 字节):表示 ObjectId 创建时的 Unix 时间戳(自 1970 年 1 月 1 日以来的秒数)。

  2. 机器标识(3 字节):用于区分不同机器生成的 ObjectId。

  3. 进程标识(2 字节):用于区分同一机器上的不同进程。

  4. 计数器(3 字节):用于确保在同一秒内生成的 ObjectId 也是唯一的。

ObjectId 的优点

  1. 唯一性ObjectId 能够在分布式系统中生成全局唯一的标识符。

  2. 时间排序:由于 ObjectId 的前 4 字节是时间戳,因此可以根据 ObjectId 排序来获取文档的创建顺序。

  3. 自动生成:MongoDB 驱动程序通常会自动为新文档生成 ObjectId

在 Python 中使用 ObjectId

在 Python 中,可以使用 bson 模块或 pymongo 模块来操作 ObjectId

1. 安装依赖

确保安装了 pymongobson

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)

注意事项

  1. 唯一性:虽然 ObjectId 是设计为全局唯一的,但在极端情况下(如短时间内高并发生成)可能会出现冲突。建议在实际应用中进行唯一性检查。

  2. 时间排序:虽然 ObjectId 的时间戳部分可以用于排序,但仅依赖 ObjectId 的时间戳进行排序可能不够精确,建议结合其他字段(如 created_at)进行排序。

  3. 兼容性ObjectId 是 MongoDB 特有的标识符,如果需要与其他数据库或系统集成,可能需要额外处理。

通过以上方法,你可以在 Python 中生成、解析和使用 ObjectId,并将其应用于 MongoDB 数据库操作中。

复制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值