电话号码的 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的主要内容,如果未能解决你的问题,请参考以下文章