【2.1】Pydantic使用方法

【一】介绍

Data validation and settings management using python type annotations.
使用Python的类型注解来进行数据校验和settings管理

pydantic enforces type hints at runtime, and provides user friendly errors when data is invalid.
Pydantic可以在代码运行时提供类型提示,数据校验失败时提供友好的错误提示

Define how data should be in pure, canonical python; validate it with pydantic.
定义数据应该如何在纯规范的Python代码中保存,并用Pydantic验证它

【二】类模型定义及使用

【1】使用 pydantic 语法创建模型类

# 导入 pydantic 中的 BaseModel 模型类
from pydantic import BaseModel
from datetime import datetime
from typing import List, Optional


# 【1】定义模型类
class User(BaseModel):
    # 定义模型类中的属性
    # 定义 ID 为 int 类型 , 没有指定 默认字段 则表示该字段为必填字段,初始化类时需要传入参数
    id: int  # 必填字段
    # 定义 name 为 str 类型并指定一个默认值
    name: str = 'dream'  # 选填字段
    # 定义 signup_time 为 datetime 类型 (需导入包 datetime) 并用 Optional 初始化
    signup_time: Optional[datetime] = None
    # 定义 friends 为 List 类型 并且规定元素类型为 int 同时指定一个默认空列表
    friends: List[int] = []  # 列表中的元素是int类型,或者可以直接转换成 int 类型
    '''
    注意字符串包裹的 int 类型 也可以 将 str 类型 强转成 int 类型
        比如 '1' ---> 1
    '''

【2】创建数据格式字典

# 【2】创建数据格式字典
external_data = {
    # id 自定义
    'id': "123",
    # 名称默认
    # signup_time 使用 自定义时间格式 --- 可以被识别的格式
    'signup_time': '2023-9-25 16:56:22',
    # friends 传入 int 类型  或者可以被 int 强转的 str 类型
    'friends': [1, 2, '3', '4']
}

【3】初始化模型类

# 【3】初始化模型类
user = User(**external_data)
print(f'当前对象 :>>> {user}')
print(f"当前对象属性 :>>>> {dir(user)}")

# 调用属性
print(user.id)
print(user.friends)
print(repr(user.signup_time))

# 输出对象数据为字典格式
print(user.dict())
当前对象 :>>> id=123 name='dream' signup_time=datetime.datetime(2023, 9, 25, 16, 56, 22) friends=[1, 2, 3, 4]

当前对象属性 :>>>> ['Config', '__abstractmethods__', '__annotations__', '__class__', '__config__', '__custom_root_type__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__fields__', '__fields_set__', '__format__', '__ge__', '__get_validators__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__json_encoder__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__post_root_validators__', '__pre_root_validators__', '__pretty__', '__private_attributes__', '__reduce__', '__reduce_ex__', '__repr__', '__repr_args__', '__repr_name__', '__repr_str__', '__schema_cache__', '__setattr__', '__setstate__', '__signature__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '__validators__', '__values__', '_abc_impl', '_calculate_keys', '_decompose_class', '_get_value', '_init_private_attributes', '_iter', 'construct', 'copy', 'dict', 'fields', 'friends', 'from_orm', 'id', 'json', 'name', 'parse_file', 'parse_obj', 'parse_raw', 'schema', 'schema_json', 'signup_time', 'to_string', 'update_forward_refs', 'validate']

123

[1, 2, 3, 4]

datetime.datetime(2023, 9, 25, 16, 56, 22)

{'id': 123, 'name': 'dream', 'signup_time': datetime.datetime(2023, 9, 25, 16, 56, 22), 'friends': [1, 2, 3, 4]}

【4】模型类初识化遇到的异常处理

  • 如果传入的类型与模型中的定义不符
# 【2】创建数据格式字典
external_data = {
    # id 自定义
    'id': "a123",
    # 名称默认
    # signup_time 使用 自定义时间格式 --- 可以被识别的格式
    'signup_time': '2023-9-25 16:56:22',
    # friends 传入 int 类型  或者可以被 int 强转的 str 类型
    'friends': [1, 2, '3', '4']
}

user = User(**external_data)
  • 报错如下
value is not a valid integer (type=type_error.integer)

【5】序列化异常信息

  • 捕获到异常并序列化异常格式化输出
# 导入 pydantic 中的 BaseModel 模型类
from pydantic import BaseModel, ValidationError
from datetime import datetime
from typing import List, Optional


# 【1】定义模型类
class User(BaseModel):
    # 定义模型类中的属性
    # 定义 ID 为 int 类型 , 没有指定 默认字段 则表示该字段为必填字段,初始化类时需要传入参数
    id: int  # 必填字段
    # 定义 name 为 str 类型并指定一个默认值
    name: str = 'dream'  # 选填字段
    # 定义 signup_time 为 datetime 类型 (需导入包 datetime) 并用 Optional 初始化
    signup_time: Optional[datetime] = None
    # 定义 friends 为 List 类型 并且规定元素类型为 int 同时指定一个默认空列表
    friends: List[int] = []  # 列表中的元素是int类型,或者可以直接转换成 int 类型
    '''
    注意字符串包裹的 int 类型 也可以 将 str 类型 强转成 int 类型
        比如 '1' ---> 1
    '''
    
# 捕获到 格式 的异常并序列化输出
try:
    User(id=1, signup_time=datetime.today(), friends=['1', 2, 'not number'])
except ValidationError as e:
    print(f'捕获到异常 :>>>> {e.json()}')
捕获到异常 :>>>> [
  {
    "loc": [
      "friends",
      2
    ],
    "msg": "value is not a valid integer",
    "type": "type_error.integer"
  }
]

【6】模型类的方法介绍

# 导入 pydantic 中的 BaseModel 模型类
from pydantic import BaseModel, ValidationError
from datetime import datetime
from typing import List, Optional


# 【1】定义模型类
class User(BaseModel):
    # 定义模型类中的属性
    # 定义 ID 为 int 类型 , 没有指定 默认字段 则表示该字段为必填字段,初始化类时需要传入参数
    id: int  # 必填字段
    # 定义 name 为 str 类型并指定一个默认值
    name: str = 'dream'  # 选填字段
    # 定义 signup_time 为 datetime 类型 (需导入包 datetime) 并用 Optional 初始化
    signup_time: Optional[datetime] = None
    # 定义 friends 为 List 类型 并且规定元素类型为 int 同时指定一个默认空列表
    friends: List[int] = []  # 列表中的元素是int类型,或者可以直接转换成 int 类型
    '''
    注意字符串包裹的 int 类型 也可以 将 str 类型 强转成 int 类型
        比如 '1' ---> 1
    '''


# 【2】创建数据格式字典
external_data = {
    # id 自定义
    'id': "123",
    # 名称默认
    # signup_time 使用 自定义时间格式 --- 可以被识别的格式
    'signup_time': '2023-9-25 16:56:22',
    # friends 传入 int 类型  或者可以被 int 强转的 str 类型
    'friends': [1, 2, '3', '4']
}

# 【3】初始化模型类
user = User(**external_data)


print("\033[31m3. --- 模型类的的属性和方法 ---\033[0m")
  • 字典序列化
# 字典序列化
print(user.dict())
{'id': 123, 'name': 'dream', 'signup_time': datetime.datetime(2023, 9, 25, 16, 56, 22), 'friends': [1, 2, 3, 4]}
  • json序列化
# json序列化
print(user.json())
{"id": 123, "name": "dream", "signup_time": "2023-09-25T16:56:22", "friends": [1, 2, 3, 4]}
  • copy数据 (注意这里的 copy 是浅拷贝)
# copy数据 (注意这里的 copy 是浅拷贝)
print(user.copy())
id=123 name='dream' signup_time=datetime.datetime(2023, 9, 25, 16, 56, 22) friends=[1, 2, 3, 4]
  • 使用解包的方式解析数据
# 使用解包的方式解析数据 (使用 类去解析数据生成对象)
print(User.parse_obj(obj=external_data))
id=123 name='dream' signup_time=datetime.datetime(2023, 9, 25, 16, 56, 22) friends=[1, 2, 3, 4]
  • 解析原生的字符串数据
# 解析原生的数据 (使用 类去解析数据生成对象)
print(User.parse_raw('{"id": "123", "signup_ts": "2020-12-22 12:22", "friends": [1, 2, "3"]}'))
id=123 name='dream' signup_time=None friends=[1, 2, 3]
  • 解析文件中的数据
# 准备数据方式一:新建pydantic_data.json
# 写入如下数据
{"id": "123", "signup_ts": "2020-12-22 12:22", "friends": [1, 2, "3"]}

# 准备数据方式二:使用pathliub模块
from pathlib import Path

path = Path('pydantic_data.json')
path.write_text('{"id": "123", "signup_ts": "2020-12-22 12:22", "friends": [1, 2, "3"]}')
# 解析文件中的数据
print(User.parse_file('pydantic_data.json'))
id=123 name='dream' signup_time=None friends=[1, 2, 3]
  • 得到对象更多的信息
# 得到的对象包含更多的信息
print(user.schema())
print(user.schema_json())
{'title': 'User', 'type': 'object', 'properties': {'id': {'title': 'Id', 'type': 'integer'}, 'name': {'title': 'Name', 'default': 'dream', 'type': 'string'}, 'signup_time': {'title': 'Signup Time', 'type': 'string', 'format': 'date-time'}, 'friends': {'title': 'Friends', 'default': [], 'type': 'array', 'items': {'type': 'integer'}}}, 'required': ['id']}

{"title": "User", "type": "object", "properties": {"id": {"title": "Id", "type": "integer"}, "name": {"title": "Name", "default": "dream", "type": "string"}, "signup_time": {"title": "Signup Time", "type": "string", "format": "date-time"}, "friends": {"title": "Friends", "default": [], "type": "array", "items": {"type": "integer"}}}, "required": ["id"]}
  • 不检验数据直接创建模型类
# 不检验数据直接创建模型类,不建议在construct方法中传入未经验证的数据
# id是字符串 是错误的
user_data = {"id": "error", "signup_ts": "2020-12-22 12 22", "friends": [1, 2, 3]}
print(User.construct(**user_data))
name='dream' signup_time=None friends=[1, 2, 3] id='error' signup_ts='2020-12-22 12 22'
  • 查看当前模型类中的所有的字段
# 查看当前模型类中的所有的字段
# 定义模型类的时候,所有字段都注明类型,字段顺序就不会乱
print(User.__fields__.keys())
name='dream' signup_time=None friends=[1, 2, 3] id='error' signup_ts='2020-12-22 12 22'
dict_keys(['id', 'name', 'signup_time', 'friends'])

【三】递归模型

  • 在一个类模型中调用另一个类模型

【1】创建模型类

# 导入 pydantic 中的 BaseModel 模型类
from pydantic import BaseModel, ValidationError
from datetime import datetime, time
from typing import List, Optional

# 定义一个 叫声类
class Sound(BaseModel):
    sound: str

# 定义一个 狗 类
class Dog(BaseModel):
    birthday: time
    weight: float = Optional[None]
    # 不同的狗有不同的叫声。递归模型(Recursive Models)就是指一个嵌套一个
    # 狗的叫声有很多种,并且这些叫声都是 Sound 类型的
    sound: List[Sound]

【2】创建数据格式

dog_data = {
    'birthday': date.today(),
    'weight': 6.66,
    'sound': [{"sound": "wang wang ~"}, {"sound": "ying ying ~"}],
}

【3】初始化对象

dog = Dog(**dog_data)
print(dog.dict())
{'birthday': datetime.date(2023, 9, 28), 'sound': [{'sound': 'wang wang ~'}, {'sound': 'ying ying ~'}]}

【四】ORM类型

  • ORM模型:从类实例创建符合ORM对象的模型

【1】创建模型表

# 导入 pydantic 中的 BaseModel 模型类
from pydantic import BaseModel, constr
from typing import List

# 导入字段
from sqlalchemy import Column, String, Integer
# 导入元组类
from sqlalchemy.dialects.postgresql import ARRAY
# 声明
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


# 【1】创建表
class CompanyOrm(Base):
    # 表名
    __tablename__ = 'companies'
    # 创建 字段 ID 为 Integer 类型且为主键,不能为空
    id = Column(Integer, primary_key=True, nullable=False)
    # 创建 字段 public_key 为 String 类型 ,且指明长度 为 20 , index 建立索引,nullable 不能为空,unique 唯一
    public_key = Column(String(20), index=True, nullable=False, unique=True)
    # 创建 字段 name 为 String 类型,指明长度 63 ,unique 唯一
    name = Column(String(63), unique=True)
    # 创建字段 domains 为 ARRAY (元组) 类型,且元组中的元素类型为 String 类型 ,指明长度 为 255
    domains = Column(ARRAY(String(255)))

【2】定义 ORM 模型表

# 【2】创建表 --- 定义一个表与上面的字段类型一样
class CompanyModel(BaseModel):
    id: int
    # constr 限制字符串
    public_key: constr(max_length=20)
    name = constr(max_length=63)
    domains: List[constr(max_length=255)]

    # 定义配置
    class Config:
        orm_mode = True

【3】创建数据字典

# 【3】创建数据字典
orm_data = {
    "id": "123",
    "public_key": "strawberry",
    "name": "Dream",
    "domains": ['example.com', 'dream.com'],
}

【4】实例化表模型对象

# 【4】实例化的到 表模型 对象
co_orm = CompanyOrm(**orm_data)

【5】实例化得到 ORM 对象

# 【5】实例化得到 ORM 对象
# ORM模型:从类实例创建符合ORM对象的模型
# co_orm 是 类的实例 使用 CompanyModel.from_orm 去校验他的数据类型
# pydantic 定义的模型类的规范
orm_obj = CompanyModel.from_orm(co_orm)
print(orm_obj)
id=123 public_key='strawberry' domains=['example.com', 'dream.com']

【6】补充

  • 提醒:选择你安装的 pydantic 版本的官方文档查看,新的版本对相关的类型进行了更新

【补充】Pydantic 插件

  • 在 Pycharm 的 插件商店中
    • 也有 Pydantic 插件,可以选择性安装

image-20230928170712308

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OAuth 2.1 是 OAuth 2.0 的升级版,它主要解决了 OAuth 2.0 在安全性和可靠性方面的一些问题。下面是 OAuth 2.1 的基本使用流程: 1. 注册应用:在使用 OAuth 2.1 之前,需要先在认证服务器上注册你的应用,注册时需要提供应用的名称、回调 URL、应用类型等信息,成功注册后会得到一个客户端 ID 和客户端密钥。 2. 获取授权码:在用户需要授权的时候,你的应用需要跳转到认证服务器的授权页面,让用户在授权页面上同意授权你的应用访问指定的资源。用户同意授权后,认证服务器会将一个授权码发送到你的应用的回调 URL 上。 3. 获取访问令牌:拿到授权码后,你的应用需要使用客户端 ID 和客户端密钥去向认证服务器请求访问令牌。在请求访问令牌的时候,需要提供授权码、回调 URL、授权类型等信息。认证服务器会验证这些信息是否正确,如果验证通过,会返回一个访问令牌和刷新令牌。 4. 使用访问令牌:拿到访问令牌后,你的应用就可以使用它去访问受保护的资源了。在访问资源的时候,需要将访问令牌作为请求头或请求参数发送到资源服务器上,资源服务器会根据访问令牌来判断是否允许访问。 5. 刷新令牌:访问令牌有一个有效期,当访问令牌过期后,你的应用需要使用刷新令牌去获取新的访问令牌。在使用刷新令牌的时候,需要提供客户端 ID、客户端密钥和刷新令牌。认证服务器会验证这些信息是否正确,如果验证通过,会返回一个新的访问令牌和新的刷新令牌。 以上就是 OAuth 2.1 的基本使用流程,不同的认证服务器可能会有一些细节上的差异,具体使用时需要参考认证服务器的文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值