Pydantic可以在代码运行时提供类型提示, 数据校验失败时提供友好的错误提示, 使用Python的类型注解来进行数据校验和settings管理

一般使用

from datetime import datetime
from typing import List
from typing import Optional from pydantic import BaseModel # 1 定义模型
class User(BaseModel):
id: int # 必须字段
name: str = "John Snow" # 有默认值,选填字段
signup_ts: Optional[datetime] = None
friends: List[int] = [] # 列表中元素是int类型或者可以直接转换成int类型 external_data = {
"id": "123",
"signup_ts": "2020-12-22 12:22",
"friends": [1, 2, "3"], # "3"是可以int("3")的
}
# 2 检验数据
user = User(**external_data)
# 3 访问数据
print(user.id, user.friends) # 实例化后调用属性
print(repr(user.signup_ts))
# .dict 方法, 返回数据字典
print(user.dict())

校验失败处理

假如数据检验不通过, 会抛出pydantic.ValidationError

from datetime import datetime

from typing import List
from typing import Optional from pydantic import BaseModel, ValidationError class User(BaseModel):
id: int # 必须字段
name: str = "John Snow" # 有默认值,选填字段
signup_ts: Optional[datetime] = None
friends: List[int] = [] # 列表中元素是int类型或者可以直接转换成int类型 external_data = {
"id": "123",
"signup_ts": "2020-12-22 12:22",
"friends": [1, 2, "3"], # "3"是可以int("3")的
} try:
User(id=1, signup_ts=datetime.today(), friends=[1, 2, "not number"])
except ValidationError as e:
print(e.json())
"""
[
{
"loc": [
"friends",
2
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
"""

模型类的的属性和方法

from datetime import datetime
from pathlib import Path
from typing import List
from typing import Optional from pydantic import BaseModel class User(BaseModel):
id: int # 必须字段
name: str = "John Snow" # 有默认值,选填字段
signup_ts: Optional[datetime] = None
friends: List[int] = [] # 列表中元素是int类型或者可以直接转换成int类型 external_data = {
"id": "123",
"signup_ts": "2020-12-22 12:22",
"friends": [1, 2, "3"], # "3"是可以int("3")的
}
user = User(**external_data) # 获得已检验数据的字典数据
print(user.dict()) # 获得已检验数据的json数据
print(user.json()) # 这里是浅拷贝
print(user.copy()) # 通过对象解析
print(User.parse_obj(external_data)) # 通过字符串解析
print(User.parse_raw('{"id": "123", "signup_ts": "2020-12-22 12:22", "friends": [1, 2, "3"]}')) path = Path('pydantic_tutorial.json')
path.write_text('{"id": "123", "signup_ts": "2020-12-22 12:22", "friends": [1, 2, "3"]}')
# 通过文本解析
print(User.parse_file(path)) # 获得对象 概要
# {'title': 'User', 'type': 'object', 'properties': {'id': ...} }
print(user.schema())
# 获得对象 概要json
# {'title': 'User', 'type': 'object', 'properties': {'id': ...} }
print(user.schema_json()) user_data = {"id": "error", "signup_ts": "2020-12-22 12 22", "friends": [1, 2, 3]} # id是字符串 是错误的
# 不检验数据直接创建模型类,不建议在construct方法中传入未经验证的数据
print(User.construct(**user_data)) # 获得所有字段
# 定义模型类的时候,所有字段都注明类型,字段顺序就不会乱
print(User.__fields__.keys())

模型嵌套

from datetime import datetime, date

from typing import List
from typing import Optional from pydantic import BaseModel class User(BaseModel):
id: int # 必须字段
name: str = "John Snow" # 有默认值,选填字段
signup_ts: Optional[datetime] = None
friends: List[int] = [] # 列表中元素是int类型或者可以直接转换成int类型 external_data = {
"id": "123",
"signup_ts": "2020-12-22 12:22",
"friends": [1, 2, "3"], # "3"是可以int("3")的
}
user = User(**external_data) class Sound(BaseModel):
sound: str class Dog(BaseModel):
birthday: date
weight: float = Optional[None]
sound: List[Sound] # 不同的狗有不同的叫声。递归模型(Recursive Models)就是指一个嵌套一个 dogs = Dog(birthday=date.today(), weight=6.66, sound=[{"sound": "wang wang ~"}, {"sound": "ying ying ~"}])
print(dogs.dict())

与ORM结合

from datetime import datetime

from typing import List
from typing import Optional from pydantic import BaseModel
from pydantic import constr
from sqlalchemy import Column, Integer, String
from sqlalchemy.dialects.postgresql import ARRAY
from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class CompanyOrm(Base):
__tablename__ = 'companies'
id = Column(Integer, primary_key=True, nullable=False)
public_key = Column(String(20), index=True, nullable=False, unique=True)
name = Column(String(63), unique=True)
domains = Column(ARRAY(String(255))) 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 co_orm = CompanyOrm(
id=123,
public_key='foobar',
name='Testing',
domains=['example.com', 'foobar.com'],
) print(CompanyModel.from_orm(co_orm))

验证器

如何使用及参数见passwords_match方法

from pydantic import BaseModel, ValidationError, validator

class UserModel(BaseModel):
name: str
username: str
password1: str
password2: str @validator('name')
def name_must_contain_space(cls, v, **kwargs):
if ' ' not in v:
raise ValueError('must contain a space')
return v.title() @validator('password2')
def passwords_match(cls, v, values, **kwargs):
"""
:param v: 当前字段的值: zxcvbn2
:param values: 已经验证的数据: {'username': 'scolvin', 'password1': 'zxcvbn'}
:param kwargs: {'field': ModelField(name='password2', type=str, required=True),
'config': <class '__main__.Config'>}
:return:
""" if 'password1' in values and v != values['password1']:
raise ValueError('passwords do not match')
return v @validator('username')
def username_alphanumeric(cls, v):
assert v.isalnum(), 'must be alphanumeric'
return v try:
UserModel(
name='samuel',
username='scolvin',
password1='zxcvbn',
password2='zxcvbn2',
)
except ValidationError as e:
print(e)
"""
2 validation errors for UserModel
name
must contain a space (type=value_error)
password2
passwords do not match (type=value_error)
"""

全部字段类型

见官方文档: Field Types

更多其他使用方法见: pydantic-docs

Pydantic使用的更多相关文章

  1. Python - pydantic 入门介绍与 Models 的简单使用

    前言 为啥要学这个,因为 FastAPI 是基于它进行开发的,而且是个不错的框架,所以有必要深入学习 前置学习 Python 类型提示:https://www.cnblogs.com/poloyy/p ...

  2. pydantic 支持Dotenv 文件设置变量

    1. 安装 pip install pydantic pip install pydantic[dotenv] 注意: 安装pip install pydantic[dotenv]时会提示no mat ...

  3. 全面理解Python中的类型提示(Type Hints)

    众所周知,Python 是动态类型语言,运行时不需要指定变量类型.这一点是不会改变的,但是2015年9月创始人 Guido van Rossum 在 Python 3.5 引入了一个类型系统,允许开发 ...

  4. Go 语言入门教程:安装

    关注公众号:雨哥写 python. 学习 Go 语言,比较下和 python 的用法,争取对 python 有更深的理解. 为什么学 Go 我主要使用 python 语言,其他语言用得不多,希望学一门 ...

  5. FastAPI 快速搭建一个REST API 服务

    最近正好在看好的接口文档方便的工具, 突然看到这个, 试了一下确实挺方便 快速示例 from fastapi import FastAPI from pydantic import BaseModel ...

  6. 三分钟了解 Python3 的异步 Web 框架 FastAPI

    快速编码,功能完善.从启动到部署,实例详解异步 py3 框架选择 FastAPI 的原因. FastAPI 介绍 FastAPI 与其它 Python-Web 框架的区别 在 FastAPI 之前,P ...

  7. 用它5分钟以后,我放弃用了四年的 Flask

    有一个非常简单的需求:编写一个 HTTP接口,使用 POST 方式发送一个 JSON 字符串,接口里面读取发送上来的参数,对其中某个参数进行处理,并返回. 如果我们使用 Flask 来开发这个接口,那 ...

  8. FastApi学习(一)

    前言 学习不止 正文 介绍 FastApi是PythonWeb框架的'新晋干员',虽然年轻但是很能打 目前已有 12k start GitHub 官网 为什么说他能打呢?它内部使用了 Python 的 ...

  9. [Python] Uvicorn+FastAPI快速搞定Restful API开发

    目录 安装模块 运行代码 运行命令 快速文档 安装模块 # 一个现代的,快速(高性能)python web框架 pip install fastapi # 主要用于加载和提供应用程序的服务器. pip ...

随机推荐

  1. binlog真的是银弹吗?有些时候也让人头疼

    大家好,我是架构摆渡人.这是实践经验系列的第三篇文章,这个系列会给大家分享很多在实际工作中有用的经验,如果有收获,还请分享给更多的朋友. binlog 用于记录用户对数据库操作的SQL语句信息,同时主 ...

  2. day14搭建博客系统项目

    day14搭建博客系统项目 1.下载代码包 [root@web02 opt]# git clone https://gitee.com/lylinux/DjangoBlog.git 2.使用pid安装 ...

  3. Scala(七)【异常处理】

    目录 一.try-catch-finally 二.Try(表达式).getOrElse(异常出现返回的默认值) 三. 直接抛出异常 一.try-catch-finally 使用场景:在获取外部链接的时 ...

  4. flink-----实时项目---day04-------1. 案例:统计点击、参与某个活动的人数和次数 2. 活动指标多维度统计(自定义redisSink)

    1. 案例 用户ID,活动ID,时间,事件类型,省份 u001,A1,2019-09-02 10:10:11,1,北京市 u001,A1,2019-09-02 14:10:11,1,北京市 u001, ...

  5. 商业爬虫学习笔记day6

    一. 正则解析数据 解析百度新闻中每个新闻的title,url,检查每个新闻的源码可知道,其title和url都位于<a></a>标签中,因为里面参数的具体形式不一样,同一个正 ...

  6. 前端页面存放token

    //本地缓存,记录token function set(type, value) { localStorage.setItem(type, value); } function get(type) { ...

  7. 【编程思想】【设计模式】【测量模式Testability】Setter_injection

    Python版 https://github.com/faif/python-patterns/blob/master/dft/setter_injection.py #!/usr/bin/pytho ...

  8. 【Linux】【Shell】【Basic】函数

    1. 函数:function,把一段独立功能的代码当作一个整体,并为之一个名字:命名的代码段,此即为函数: 注意:定义函数的代码段不会自动执行,在调用时执行:所谓调用函数,在代码中给定函数名即可: 函 ...

  9. 35、搜索插入位置 | 算法(leetode,附思维导图 + 全部解法)300题

    零 标题:算法(leetode,附思维导图 + 全部解法)300题之(35)搜索插入位置 一 题目描述 二 解法总览(思维导图) 三 全部解法 1 方案1 1)代码: // 方案1 "无视要 ...

  10. DevOps和SRE的区别

    目录 一.误区 二.DevOps 和 SRE 定义 三.两者产生背景和历史 四.两者的职能不同 五.工作内容不同 六.DevOps 和 SRE 关系 七.附录:技能点 DevOps SRE 一.误区 ...