[英]pydantic custom data type for phone number : value_error.missing
mysql schema for user用户的 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)
my pydantic model is我的 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]
i want to create a custom datatype for phone number...so i can use it at multiple places....i am trying like below我想为电话号码创建一个自定义数据类型......所以我可以在多个地方使用它......我正在尝试如下
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
via postman, i am sending通过 postman,我正在发送
{
"phone": "+917777777777"
}
i see 400 error in postman我在 postman 中看到 400 错误
[
{
"loc": [
"phone",
"phone"
],
"msg": "field required",
"type": "value_error.missing"
}
]
Any inputs on what i am doing wrong above关于我在上面做错的任何输入
This doesn't work because you are passing in:这不起作用,因为您正在传递:
{
"phone": "+917777777777"
}
while the model has the structure UserPatchEntity.Phone.phone
.而 model 具有结构
UserPatchEntity.Phone.phone
。
In order to make this work, I see two options:为了完成这项工作,我看到了两个选项:
validator
) validator
) Fixing the 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
Send this instead:改为发送:
{
"phone": {
"phone": "+917777777777"
}
}
It should work now.它现在应该可以工作了。
validator
to the Parent Model validator
移至父 Model I would assume that the following is more in line what you want:我会假设以下内容更符合您的要求:
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
With that you can pass in phone
in the body as you would expect:有了它,您可以按预期将
phone
传递到体内:
{
"phone": "+917777777777"
}
Assuming you're using FastAPI, in both cases, you'd get the following error if the phone number is too short, too long, or contains invalid characters:假设您使用的是 FastAPI,在这两种情况下,如果电话号码太短、太长或包含无效字符,您都会收到以下错误:
{
"detail": [
{
"loc": [
"body",
"phone"
],
"msg": "Phone Number Invalid.",
"type": "value_error"
}
]
}
Pydantic has a constr
(Constrained String) type, which allows you to define the minimum and maximum length, and a few other things. constr
有一个 constr(约束字符串)类型,它允许您定义最小和最大长度,以及其他一些东西。 You could use the following instead of str
for the phone
field, eg:您可以将以下内容代替
str
用于phone
字段,例如:
class UserPatchEntity(BaseModel): ... phone: Optional[ constr( strip_whitespace=True, min_length=9, max_length=15, ) ]
It also allows you to directly specify a regex
string, eg:它还允许您直接指定
regex
字符串,例如:
class UserPatchEntity(BaseModel): ... phone: Optional[ constr( strip_whitespace=True, regex=r"^(\+)[1-9][0-9\-\(\)\.]{9,15}$", ) ]
Which would save you writing the explicit validator
.这样可以节省您编写显式
validator
的时间。
If you continue using regular expressions "directly", I would suggest to compile()
them to make them a bit faster.如果您继续“直接”使用正则表达式,我建议您
compile()
它们以使它们更快一点。
Assuming you are using FastAPI, you can navigate to http://localhost:8000/docs
, when the app is running, where you'll find a full OpenAPI interface.假设您使用的是 FastAPI,您可以在应用程序运行时导航到
http://localhost:8000/docs
,您将在其中找到完整的 OpenAPI 接口。 You can send payloads directly from there and it also shows you the signature for each endpoint.您可以直接从那里发送有效负载,它还会向您显示每个端点的签名。 In the first case, if you defined an endpoint like this:
在第一种情况下,如果您定义了这样的端点:
@router.post("/user/") async def post_user(user_patch_entity: UserPatchEntity): return user_patch_entity.phone
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.