最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

pydantic進階用法示例詳解

 更新時間:2023年03月15日 14:24:24   作者:it_miclon  
這篇文章主要為大家介紹了pydantic進階用法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

正文

pydantic是一個Python的數(shù)據(jù)驗證和轉(zhuǎn)換庫,它的特點是輕量、快速、可擴展、可配置。筆者常用的用于數(shù)據(jù)接口schema定義與檢查。

具體的基本用法本文不再做過多的介紹,可以參考pydantic官方文檔。本文主要是結(jié)合實際項目開發(fā)中遇到的問題和解題思路,介紹一些pydantic的高階玩法。

當前現(xiàn)狀

在項目中,pydantic的定義是在數(shù)據(jù)的出口進行規(guī)范化,從而使得下游接受方能更快地去解析和清洗這些數(shù)據(jù)。

from pydantic import BaseModel, Field

# 定義數(shù)據(jù)模型
class Project(BaseModel):
    url: str = Field(...)
    title: str = Field(...)
    content: str = Field(...)
    company: List[Dict] = Field(default=[])
    industry: str = Field(...)

以上是簡單的一個數(shù)據(jù)模型定義,代碼僅為示例,隱去了一些字段和配置。也就是我們必須傳輸給Project模型對應的數(shù)據(jù)才可以通過它的數(shù)據(jù)校驗,否則就無法繼續(xù)向下(可能是發(fā)往下游)

這么做一直以來沒什么問題,直到本次項目中的接口返回出現(xiàn)了大更新,使得之前的所有代碼層做的數(shù)據(jù)字段映射必須重新對應匹配。

比如之前title字段對應的是title,現(xiàn)在變成了detail-article-title

這使得我們必須在代碼層做諸如:

# project_data均為接口返回的數(shù)據(jù),加數(shù)據(jù)演示

# 之前的代碼
project_data = {
    "url": "https://www.baidu.com",
    "title": "百度一下,你就知道",
}
project = Project(
    **project_data
)

# 現(xiàn)在的代碼
project_data = {
  "detail": {
      "url": "xxx"
      "article": {
          "title": "項目標題",
      }
  }
}
project = Project(
    url=project_data["detail"]["url"],
    title=project_data["detail"]["article"]["title"],
)

以上代碼取值變得復雜,這還沒考慮到數(shù)據(jù)可能存在出錯的問題,比如detail字段不存在,這樣就會導致KeyError異常。

而且這并不是夸張的舉例(因為事實情況更復雜)。

我怎么能容忍這種情況呢?

解決方案

我當然不是想摒棄掉pydantic,而是想找到一種結(jié)合它更優(yōu)雅的方式來解決這個問題。

于是我第一時間想到了jmespath模塊,因為它是一個JSON查詢語言,可以用來在JSON數(shù)據(jù)中查找和提取數(shù)據(jù)。

from jmespath import search
project_data = {
    "detail": {
        "article": {
            "title": "項目標題",
        }
    }
}

title = search("detail.article.title", project_data)
assert title == "項目標題"  # True

# 即使是path不存在,也不會異常,而是返回None
assert search("detail.article.title1", project_data) is None  # True

所以我打算做一個結(jié)合pydanticjmespath的方式來解決這個問題。

class Project(BaseModel):
    url: str = Field(...)
    title: str = Field(...)
    content: str = Field(...)
    company: List[Dict] = Field(default=[])
    industry: str = Field(...)

    @root_validator(pre=True, skip_on_failure=True)
    def data_converter(cls, v):
        return {
            "url": search("detail.id", v),
            "title": search("detail.article.title", v),
            "content": search("detail.article.content", v),
            "company": search("company[*].name", v),
            "industry": search("industry", v)
        }
    
    @validator("url")
    def url_validator(cls, v):
        # 由于這里的v是拿到的ID,需要組合成url
        return f"https://xxxxx/{v}"

從代碼中可以知道,我是在root_validator中提前做了數(shù)據(jù)的轉(zhuǎn)換,將jmespath的查詢結(jié)果賦值給對應的字段。

但是做完之后我越看越變扭,我為了做這個事情,先要申明所有字段,還要對這些字段一一映射。

于是,我想到了pydanticConfig類,它可以用來配置pydantic的一些行為。而且通過查看源碼,我認為我可以通過Field類中輸入一個path變量,告訴未來的處理器,這個path是用來做數(shù)據(jù)提取的。

class Project(BaseModel):
    url: str = Field(..., path="temporaryLibrary.id")
    company_names: str = Field(..., path="company[0].enterprise.name")
    versions: List[str] = Field(..., path="versionList[*].id")

當然現(xiàn)在代碼是沒有任何意義的,因為path是我們自定義的,pydantic并不知道如何處理它。

所以下一步我們要做的是,如何更好的讓pydantic知道如何處理path。

在多次翻閱它源代碼,并結(jié)合官方文檔中對Model類的介紹,我找到了一個可行的方案。

Pydantic models can be created from arbitrary class instances to support models that map to ORM objects.

也就是說,我可以將原始數(shù)據(jù)通過from_orm傳遞給pydantic的模型,然后通過Data binding的方式,將數(shù)據(jù)綁定到模型中。Data binding允許我們自定義數(shù)據(jù)的取值來源。

class ProjectGetter(GetterDict):

    def get(self, key: str, default: Any) -> Any:  # noqa
        # 由于getter_dict所能拿到的“數(shù)據(jù)權(quán)限”相對較低,
        # 也就是它的權(quán)限僅僅是處理數(shù)據(jù),而不是處理模型,
        # 所以我們需要自己去拿到模型,然后再去拿到path
        model, data = self._obj['model'], self._obj['data']
        for name, field in model.__fields__.items():
            path = field.field_info.extra.get('path')
            if path and name == key:
                return search(path, data)
        return default


class Project(BaseModel):
    url: str = Field(..., path="detail.id")
    company_names: str = Field(..., path="company[0].enterprise.name")
    versions: List[str] = Field(..., path="versionList[*].id")

    @validator("url")
    def url_validator(cls, v):
        return f"https://www.baidu.com/{v}"

    class Config:
        # 通過orm_mode指定數(shù)據(jù)的來源
        orm_mode = True
        # 通過getter_dict指定數(shù)據(jù)的獲取方式
        getter_dict = ProjectGetter

project_data = {
    "detail": {
        "id": 1,
        "article": {
            "title": "項目標題",
        }
    },
    "company": [
      {
        "enterprise": {
          "name": "企業(yè)名稱1"
        }
      },
      {
        "enterprise": {
          "name": "企業(yè)名稱2"
        }
      }
    ],
    "versionList": [{"id": "1.0"}, {"id": "2.0"}]
}
project = Project.from_orm({"model": Project, "data": project_data})
print(project)
# url='https://www.baidu.com/1' company_names='企業(yè)名稱1' versions=['1.0', '2.0']

這樣我們在業(yè)務端,只需要對Field指定其對應數(shù)據(jù)提取的path,而不需要再去寫一堆的validator或者是在數(shù)據(jù)進入前做一堆的數(shù)據(jù)轉(zhuǎn)換。

總結(jié)

通過這個小例子,我們可以看到,pydantic的靈活性是非常強的,它可以通過Config類來配置一些行為,而且它的Field類也可以通過extra參數(shù)來傳遞一些額外的信息。這大大的提高了我們的對數(shù)據(jù)的處理能力。筆者也會在后續(xù)的文章中,繼續(xù)分享pydantic的一些使用技巧。

以上就是pydantic進階用法示例詳解的詳細內(nèi)容,更多關于pydantic進階用法的資料請關注腳本之家其它相關文章!

相關文章

  • 一文掌握python中的__init__的意思及使用場景分析

    一文掌握python中的__init__的意思及使用場景分析

    __init__是構(gòu)造方法,誰調(diào)用,表示誰(更直觀的理解就是類的方法中,誰調(diào)用,表示誰,見下面第一個代碼)??!并不是必選項,也就是說在類中,這個不是必須用的,那什么場景需要用到,什么場景不需要用到呢,感興趣的朋友跟隨小編一起看看吧
    2023-02-02
  • 使用apidocJs快速生成在線文檔的實例講解

    使用apidocJs快速生成在線文檔的實例講解

    下面小編就為大家分享一篇使用apidocJs快速生成在線文檔的實例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • python 畫二維、三維點之間的線段實現(xiàn)方法

    python 畫二維、三維點之間的線段實現(xiàn)方法

    今天小編就為大家分享一篇python 畫二維、三維點之間的線段實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-07-07
  • 讓python 3支持mysqldb的解決方法

    讓python 3支持mysqldb的解決方法

    這篇文章主要介紹了關于讓python 3支持mysqldb的解決方法,文中給出解決的示例代碼,相信對大家具有一定的參考價值,有需要的朋友可以一起來看看。
    2017-02-02
  • Python的Bottle框架中返回靜態(tài)文件和JSON對象的方法

    Python的Bottle框架中返回靜態(tài)文件和JSON對象的方法

    這篇文章主要介紹了Python的Bottle框架中返回靜態(tài)文件和JSON對象的方法,Bottle框架在Python開發(fā)者中具有很高的人氣,需要的朋友可以參考下
    2015-04-04
  • python實現(xiàn)黃金分割法的示例代碼

    python實現(xiàn)黃金分割法的示例代碼

    這篇文章主要介紹了python實現(xiàn)黃金分割法的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • PaddleOCR 識別表情包文字示例詳解

    PaddleOCR 識別表情包文字示例詳解

    這篇文章主要為大家介紹了PaddleOCR 識別表情包文字示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Python 腳本實現(xiàn)淘寶準點秒殺功能

    Python 腳本實現(xiàn)淘寶準點秒殺功能

    這篇文章主要介紹了python實現(xiàn)淘寶準點秒殺腳本,本文圖文實例相結(jié)合給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-11-11
  • Flask搭建虛擬環(huán)境并運行第一個flask程序

    Flask搭建虛擬環(huán)境并運行第一個flask程序

    這篇文章主要介紹了Flask搭建虛擬環(huán)境并運行第一個flask程序,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • python使用cookie庫操保存cookie詳解

    python使用cookie庫操保存cookie詳解

    Python中Cookie模塊(python3中為http.cookies)提供了一個類似字典的特殊對象SimpleCookie,其中存儲并管理著稱為Morsel的cookie值集合,這里介紹了python操作cookie的使用方法
    2014-03-03

最新評論

上饶县| 吴旗县| 漳州市| 丰镇市| 青川县| 普安县| 临城县| 高邑县| 二连浩特市| 平阴县| 江陵县| 获嘉县| 青州市| 左权县| 怀柔区| 新宾| 宁波市| 宝山区| 栾城县| 贺兰县| 广元市| 诸城市| 兰西县| 新巴尔虎左旗| 鄂州市| 磴口县| 甘谷县| 布拖县| 和林格尔县| 蒙阴县| 类乌齐县| 博湖县| 亚东县| 济阳县| 噶尔县| 呼和浩特市| 清苑县| 丽水市| 大荔县| 喀喇沁旗| 壤塘县|