乐趣区

关于后端:FastAPI-开发中数据校验利器-Pydantic-介绍与集成使用

前言

当咱们在解决一些数据来自零碎内部的时候,可能来自 API、终端用户输出或者其余路径,Web 开发中有句话叫做:永远不要置信用户的输出

所以,咱们可能须要查看、校验这些数据,将这些数据格式化、标准化,以至于这些数据满足咱们实在程序的数据输出,保障我的项目的正确执行。

Pydantic 介绍

Pydantic 是一个 Python 库,它提供了一种简略不便的办法来验证和操作数据。它的创立是为了帮忙简化数据验证过程并进步开发人员的效率。Pydantic 与 Python 的数据结构无缝集成,并提供灵便且用户敌对的 API 来定义和验证数据。应用 Pydantic,开发人员能够定义他们的数据结构和验证规定,库将主动验证传入数据并在不满足任何规定时引发谬误。这有助于确保我的项目中应用的数据是统一的并符合要求的规范。

官网介绍:应用 Python 类型正文的数据验证和设置治理。pydantic 在运行时强制执行类型提醒,并在数据有效时提供用户敌对的谬误。定义数据应该如何在纯正的、标准的 Python 中;用 pydantic 验证它。

Pydantic 提供 BaseModel 让开发者可能通过继承该类并且利用 typing 注记类别属性的数据类型,保障咱们不必写过多的代码就领有根本的 数据验证 性能。

定义模型时,被用作申请主体对象和申请 - 响应对象的类型提醒。在本文中,咱们将简略看一下在申请体中应用 Pydantic 模型来解决 POST 申请。

Pydantic 装置

pip install pydantic

然而如果你是间接装置好了 FastAPI,这一步能够跳过,因为 FastAPI 框架就应用了 Pydantic。

Pydantic 长处

  • 易于应用:Pydantic 很容易装置与应用,并且有一个简略的 API,使得所有开发者都能够疾速上手应用。
  • 疾速验证:Pydantic 疾速无效地执行数据验证,使其适宜于在高性能的应用程序中应用。
  • 主动生成文档:Pydantic 能够为你的数据模型主动生成文档,节省时间,并且更容易了解你的数据结构。
  • 类型提醒反对:Pydantic 反对类型提醒,使开发人员更容易定义数据结构,防止在代码中呈现谬误。
  • 与 FastAPI 集成:Pydantic 能够很容易地与 FastAPI(一个高性能的 Python 网络框架)集成,为 API 提供主动申请和响应验证。
  • 自定义验证规定:Pydantic 容许开发人员定义自定义的验证规定,使得在须要的时候能够实现简单的验证逻辑。
  • 统一的数据:Pydantic 确保我的项目中应用的数据是统一的,并合乎所需的规范,缩小了谬误的危险,使代码库的保护更加容易。

什么是类型注解

Python 是动静类型的语言,所以在同一个命名空间中,变量的值能够是字符串也能够是数组,比方:

>>> x = 4
>>> type(x)
<class 'int'>
>>> x = "hello, 宇宙之一粟"
>>> type(x)
<class 'str'>

大概在 Python 3.5 起引入了 type hints 类型注解,尽管 Python 在运行时不强制执行函数和变量类型注解,但这些注解可用于类型查看器、IDE、动态查看器等第三方工具,这些工具就能够帮忙咱们侦测类型上的谬误。

最简略的注解形式如下:

def hello(name: str) -> str:
    return 'Hello' + name

这外面的 : str 申明 name 字段为字符串,如果传入 int 类型,编译器就会失去报错:

利用 Pydantic 定义模型

咱们在定义如下 Book 模型的时候,咱们申明了 id 为数字类型,Name 到 ISBN 都为字符串类型,Tags 为列表类型,通过继承自 BaseModel 的个性,Pydantic 会主动帮咱们验证型态的正确性:

from pydantic import BaseModel

class Book(BaseModel):
    id: int
    Name: str
    Author: str
    Publisher: str
    ISBN: str
    Tags: list[str]


HeadFirstPython = Book(
    id = 1,
    Name = 'Head First Python, 2nd Edition',
    Author = 'Paul Barry',
    Publisher ="O'Reilly Media, Inc.",
    ISBN = "9781491919538",
    Tags = ["Python", "Head Frist"]
)

如果这样定义之后,咱们的上述的 HeadFirstPython 不会报任何谬误,然而如果咱们的 id 还没定义,如下:

from pydantic import BaseModel

class Book(BaseModel):
    id: int
    Name: str
    Author: str
    Publisher: str
    ISBN: str
    Tags: list[str]


HeadFirstPython = Book(
    id = "notdefineyet",
    Name = 'Head First Python, 2nd Edition',
    Author = 'Paul Barry',
    Publisher ="O'Reilly Media, Inc.",
    ISBN = "9781491919538",
    Tags = ["Python", "Head Frist"]
)

则会报一个 id 类型谬误的报错:

然而如果你定义 id 为 id = "1", 则不会报错,因为 Pydantic 帮忙咱们主动实现了类型转换,如果想要严格控制 int 类型,须要导入 StrictIntStrictString 同理,代码如下:

from pydantic import BaseModel, StrictInt, StrictStr

class Book(BaseModel):
    # id: int
    id: StrictInt
    # Name: str
    Name: StrictStr
    Author: str
    Publisher: str
    ISBN: str
    Tags: list[str]


HeadFirstPython = Book(
    # id = "1",
    id = 1,
    # Name = 'Head First Python, 2nd Edition',
    Name = 27546, # 此处会报错,
    Author = 'Paul Barry',
    Publisher ="O'Reilly Media, Inc.",
    ISBN = "9781491919538",
    Tags = ["Python", "Head Frist", 1]
)

print('output>', HeadFirstPython.dict())

报错信息如下:

pydantic.error_wrappers.ValidationError: 1 validation error for Book
Name
  str type expected (type=type_error.str)

更多 Pydantic 的类型具体阐明,请查看官网文档,点此处。

Pydantic 的工作形式

Pydantic 的工作形式是容许开发人员应用 Python 类来定义数据模型。这些类继承自 Pydantic 提供的 BaseModel 类,能够包含类型提醒、默认值和验证规定。当收到数据时,Pydantic 应用数据模型来验证传入的数据,并确保其合乎所定义的要求。

在验证过程中,Pydantic 对照数据模型中定义的类型提醒和验证规定,检查数据中的每个字段。如果数据不符合要求,Pydantic 会提出一个谬误,并进行验证过程。如果数据是无效的,Pydantic 就会创立一个数据模型的实例,用传入的数据来填充它,并将其返回给用户。

Pydantic 还提供了一些高级性能,例如字段别名,自定义验证函数,以及对嵌套数据模型的反对,使得它能够解决宽泛的数据验证场景。此外,Pydantic 反对序列化和反序列化,容许依据须要将数据转换为 Python 数据结构、JSON 和其余格局。

Pydantic 与 FastAPI 集成开发 Demo:写一个 todo 利用

假如咱们通过 FastAPI 集成 Pydantic 的长处,写一个 todo 利用的接口实现 Todo 利用的创立和查看性能,文件目录构造如下:

首先,咱们通过 Pydantic 新建 todo 利用的 model.py:

from pydantic import BaseModel, StrictInt


class Todo(BaseModel):
    id: StrictInt
    item: str

先简略定义了两个字段:

  • id:数字类型,作为惟一标识
  • item: 字符串类型

而后新建路由文件夹 router,在其中建设一个 todo_router.py 文件,写入如下代码:

from fastapi import APIRouter
from models.model import Todo

todo_router = APIRouter()

todo_list = []

@todo_router.post("/todo")
async def add_todo(todo: Todo) -> dict:
    todo_list.append(todo)
    return {"message": "Todo added successfully"}

@todo_router.get("/todo")
async def retrieve_todos() -> dict:
    return {"todos": todo_list}

回到 main.py:

from fastapi import FastAPI

from routers.todo_router import todo_router # importing router

app = FastAPI() # create an app instance



@app.get('/') 
async def home() -> dict:
    return {"message": "Welcome to my Page"}

app.include_router(todo_router)

验证 Pydantic 是否失效

执行命令如下:

$ uvicorn main:app --reload --port 8888
INFO:     Will watch for changes in these directories: ['C:\\Users\\Wade\\Desktop\\FastAPI\\fastwebprojects']
INFO:     Uvicorn running on http://127.0.0.1:8888 (Press CTRL+C to quit)
INFO:     Started reloader process [22288] using StatReload
INFO:     Started server process [25008]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

另外关上一个终端,执行 GET 申请,失去空的 todo 列表:

$ curl -X 'GET' 'http://127.0.0.1:8888/todo' -H 'accept: applicaion/json'
{"todos":[]}

接着执行 POST 申请,如下:

curl -X POST http://127.0.0.1:8888/todo -H 'accept: application/json' -H 'Content-Type: application/json' -d '{}'
{"detail":[{"loc":["body","id"],"msg":"field required","type":"value_error.missing"},{"loc":["body","item"],"msg":"field required","type":"value_error.missing"}]}

如果咱们传入一个空的数组,将会失去一串由 Pydantic 校验生成的 JSON 数据,格式化如下:

{
  "detail": [
    {
      "loc": [
        "body",
        "id"
      ],
      "msg": "field required",
      "type": "value_error.missing"
    },
    {
      "loc": [
        "body",
        "item"
      ],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

该 JSON 数据提醒咱们 id 和 item 都是必须字段 "msg": "field required", 因而,咱们更改一下 POST 申请,如下:

$ curl -X POST http://127.0.0.1:8888/todo -H 'accept: application/json' -H 'Content-Type: application/json' -d '{"id": 1,"item":"write a todo project"}'    
{"message":"Todo added successfully"}

此时咱们能够看到创立一个 todo 事项胜利,返回了 {"message":"Todo added successfully"} !

再执行一次 curl 的 GET 申请,后果如下,能够看到刚刚创立胜利的今日 todo—— item“write a todo project”, id 值为 1:

$ curl -X 'GET' 'http://127.0.0.1:8888/todo' -H 'accept: applicaion/json'        
{"todos":[{"id":1,"item":"write a todo project"}]}

关上 http://127.0.0.1:8888/docs,能够看到如下界面:

此处 Todo 就是咱们刚刚定义的 Model 中限定的字段类型:

总结

本文介绍了 Pydantic 以及它的装置与工作形式,Pydantic 提供了主动的数据验证,进步了性能,并且反对简单的数据结构,使得构建强壮和可保护的应用程序更加容易。尽管本文只是简略的校验数据的存在性,还有更多比方邮箱、明码格局等等,Pydantic 都会提供,心愿本文抛砖引玉,让大家摸索和学习 Pydantic 的更多功能。

心愿本文能对你有所帮忙,如果喜爱本文,能够点个关注.

下一篇文章见!宇宙古今无有穷期,毕生不过顷刻,当思奋争。

参考链接:

  • What Is Pydantic And How Is It Used
退出移动版