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

pydantic進(jìn)階用法示例詳解

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

正文

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

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

當(dāng)前現(xiàn)狀

在項(xiàng)目中,pydantic的定義是在數(shù)據(jù)的出口進(jìn)行規(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(...)

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

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

比如之前title字段對(duì)應(yīng)的是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": "項(xiàng)目標(biāo)題",
      }
  }
}
project = Project(
    url=project_data["detail"]["url"],
    title=project_data["detail"]["article"]["title"],
)

以上代碼取值變得復(fù)雜,這還沒(méi)考慮到數(shù)據(jù)可能存在出錯(cuò)的問(wèn)題,比如detail字段不存在,這樣就會(huì)導(dǎo)致KeyError異常。

而且這并不是夸張的舉例(因?yàn)槭聦?shí)情況更復(fù)雜)。

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

解決方案

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

于是我第一時(shí)間想到了jmespath模塊,因?yàn)樗且粋€(gè)JSON查詢語(yǔ)言,可以用來(lái)在JSON數(shù)據(jù)中查找和提取數(shù)據(jù)。

from jmespath import search
project_data = {
    "detail": {
        "article": {
            "title": "項(xiàng)目標(biāo)題",
        }
    }
}

title = search("detail.article.title", project_data)
assert title == "項(xiàng)目標(biāo)題"  # True

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

所以我打算做一個(gè)結(jié)合pydanticjmespath的方式來(lái)解決這個(gè)問(wèn)題。

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é)果賦值給對(duì)應(yīng)的字段。

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

于是,我想到了pydanticConfig類,它可以用來(lái)配置pydantic的一些行為。而且通過(guò)查看源碼,我認(rèn)為我可以通過(guò)Field類中輸入一個(gè)path變量,告訴未來(lái)的處理器,這個(gè)path是用來(lái)做數(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")

當(dāng)然現(xiàn)在代碼是沒(méi)有任何意義的,因?yàn)?code>path是我們自定義的,pydantic并不知道如何處理它。

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

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

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

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

class ProjectGetter(GetterDict):

    def get(self, key: str, default: Any) -> Any:  # noqa
        # 由于getter_dict所能拿到的“數(shù)據(jù)權(quán)限”相對(duì)較低,
        # 也就是它的權(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:
        # 通過(guò)orm_mode指定數(shù)據(jù)的來(lái)源
        orm_mode = True
        # 通過(guò)getter_dict指定數(shù)據(jù)的獲取方式
        getter_dict = ProjectGetter

project_data = {
    "detail": {
        "id": 1,
        "article": {
            "title": "項(xiàng)目標(biāo)題",
        }
    },
    "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']

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

總結(jié)

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

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

相關(guān)文章

  • 一文掌握python中的__init__的意思及使用場(chǎng)景分析

    一文掌握python中的__init__的意思及使用場(chǎng)景分析

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

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

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

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

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

    讓python 3支持mysqldb的解決方法

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

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

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

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

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

    PaddleOCR 識(shí)別表情包文字示例詳解

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

    Python 腳本實(shí)現(xiàn)淘寶準(zhǔn)點(diǎn)秒殺功能

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

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

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

    python使用cookie庫(kù)操保存cookie詳解

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

最新評(píng)論

道孚县| 正镶白旗| 大连市| 奎屯市| 益阳市| 手游| 沭阳县| 顺平县| 日照市| 拜泉县| 慈溪市| 怀仁县| 颍上县| 鄂尔多斯市| 托克托县| 重庆市| 福泉市| 盐山县| 南郑县| 略阳县| 招远市| 滦平县| 蓝山县| 稷山县| 永胜县| 南京市| 新昌县| 岚皋县| 喀喇沁旗| 神木县| 宁波市| 正宁县| 沧源| 分宜县| 景宁| 屏山县| 木兰县| 西畴县| 苗栗市| 宜宾市| 阿拉尔市|