繁体   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