簡體   English   中英

電話號碼的 pydantic 自定義數據類型:value_error.missing

[英]pydantic custom data type for phone number : value_error.missing

用戶的 mysql 架構

user_id     binary(16) 
first_name  varchar(32) 
last_name   varchar(32) 
email       varchar(255)
phone       varchar(32) 
role        enum('member','admin','operator')
created_on  datetime
updated_on  datetime
id   varchar(32)

我的 pydantic model 是

class UserPatchEntity(BaseModel):
    user_id: Optional[UUID]
    first_name: Optional[str] = Field(min_length=1, max_length=32)
    last_name: Optional[str] = Field(min_length=1, max_length=32)
    email: Optional[EmailStr]
    phone: Optional[Phone]---------------> HERE
    role:  Optional[RoleType]

我想為電話號碼創建一個自定義數據類型......所以我可以在多個地方使用它......我正在嘗試如下

class Phone(BaseModel):
    phone: str
    @validator('phone')
    def phone_validation(cls, v):
        phone = v.phone.get("phone")
        logger.debug(f"phone in 2 validator:{v}")
        regex = r"^(\+)[1-9][0-9\-\(\)\.]{9,15}$"
        if v and not re.search(regex, v, re.I):
            raise ValueError("Phone Number Invalid.")
        return v
    class Config:
        orm_mode = True
        use_enum_values = True

通過 postman,我正在發送

{
    "phone": "+917777777777"
}

我在 postman 中看到 400 錯誤

[
    {
        "loc": [
            "phone",
            "phone"
        ],
        "msg": "field required",
        "type": "value_error.missing"
    }
]

關於我在上面做錯的任何輸入

這不起作用,因為您正在傳遞:

{
    "phone": "+917777777777"
}

而 model 具有結構UserPatchEntity.Phone.phone

為了完成這項工作,我看到了兩個選項:

1.適配JSON Body(並修復validator

修復validator

class Phone(BaseModel):
    phone: str
    @validator("phone")
    def phone_validation(cls, v):
        # phone = v.phone.get("phone") #  <-- This line needs to be removed.
        logger.debug(f"phone in 2 validator:{v}")
        regex = r"^(\+)[1-9][0-9\-\(\)\.]{9,15}$"
        if v and not re.search(regex, v, re.I):
            raise ValueError("Phone Number Invalid.")
        return v

    class Config:
        orm_mode = True
        use_enum_values = True

改為發送:

{
  "phone": {
    "phone": "+917777777777"
  }
}

它現在應該可以工作了。

2. 將validator移至父 Model

我會假設以下內容更符合您的要求:

class UserPatchEntity(BaseModel):
    user_id: Optional[UUID]
    first_name: Optional[str] = Field(min_length=1, max_length=32)
    last_name: Optional[str] = Field(min_length=1, max_length=32)
    email: Optional[EmailStr]
    phone: Optional[str]  # <-- This is a str now, everything else stays the same
    role:  Optional[RoleType]

    @validator("phone")
    def phone_validation(cls, v):
        logger.debug(f"phone in 2 validator:{v}")
        regex = r"^(\+)[1-9][0-9\-\(\)\.]{9,15}$"
        if v and not re.search(regex, v, re.I):
            raise ValueError("Phone Number Invalid.")
        return v

    class Config:
        orm_mode = True
        use_enum_values = True

有了它,您可以按預期將phone傳遞到體內:

{
    "phone": "+917777777777"
}

假設您使用的是 FastAPI,在這兩種情況下,如果電話號碼太短、太長或包含無效字符,您都會收到以下錯誤:

{
  "detail": [
    {
      "loc": [
        "body",
        "phone"
      ],
      "msg": "Phone Number Invalid.",
      "type": "value_error"
    }
  ]
}

注釋/提示:

  • constr有一個 constr(約束字符串)類型,它允許您定義最小和最大長度,以及其他一些東西。 您可以將以下內容代替str用於phone字段,例如:

     class UserPatchEntity(BaseModel): ... phone: Optional[ constr( strip_whitespace=True, min_length=9, max_length=15, ) ]

    它還允許您直接指定regex字符串,例如:

     class UserPatchEntity(BaseModel): ... phone: Optional[ constr( strip_whitespace=True, regex=r"^(\+)[1-9][0-9\-\(\)\.]{9,15}$", ) ]

    這樣可以節省您編寫顯式validator的時間。

  • 如果您繼續“直接”使用正則表達式,我建議您compile()它們以使它們更快一點。

  • 假設您使用的是 FastAPI,您可以在應用程序運行時導航到http://localhost:8000/docs ,您將在其中找到完整的 OpenAPI 接口。 您可以直接從那里發送有效負載,它還會向您顯示每個端點的簽名。 在第一種情況下,如果您定義了這樣的端點:

     @router.post("/user/") async def post_user(user_patch_entity: UserPatchEntity): return user_patch_entity.phone

    它會顯示這樣的文檔: 在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM