电话号码的 pydantic 自定义数据类型:value_error.missing

Posted

技术标签:

【中文标题】电话号码的 pydantic 自定义数据类型:value_error.missing【英文标题】:pydantic custom data type for phone number : value_error.missing 【发布时间】:2022-01-21 14:54:44 【问题描述】:

用户的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 模型是

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

通过邮递员,我正在发送


    "phone": "+917777777777"

我在邮递员中看到 400 错误

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

关于我在上面做错的任何输入

【问题讨论】:

【参考方案1】:

这不起作用,因为您正在传递:


    "phone": "+917777777777"

而模型的结构为UserPatchEntity.Phone.phone

为了完成这项工作,我看到了两个选项:

1。调整 JSON 正文(并修复 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 移动到父模型

我认为以下内容更符合您的要求:

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"
    
  ]

注意事项/提示:

Pydantic 有一个constr(约束字符串)类型,它允许您定义最小和最大长度,以及其他一些东西。对于 phone 字段,您可以使用以下内容而不是 str,例如:

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

它会显示这样的文档:

【讨论】:

以上是关于电话号码的 pydantic 自定义数据类型:value_error.missing的主要内容,如果未能解决你的问题,请参考以下文章

pydantic学习与使用-1.pydantic简介与基础入门

pydantic学习与使用-9.枚举类型(enum)

FastAPI Web框架 [Pydantic]

FastAPI Web框架 [Pydantic]

FastAPI Web框架 [Pydantic]

pydantic学习与使用-2.基本模型(BaseModel)使用