es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Tipo de dato personalizado para número de teléfono en pydantic: value_error.missing

Esquema MySQL para usuario:

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)

Mi modelo Pydantic es:

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]---------------> AQUÍ
    role:  Optional[RoleType]

Quiero crear un tipo de dato personalizado para el número de teléfono, de modo que pueda usarlo en varios lugares. Estoy intentando hacerlo de la siguiente manera:

class Phone(BaseModel):
    phone: str

    @validator('phone')
    def phone_validation(cls, v):
        phone = v.phone.get("phone")
        logger.debug(f"teléfono en el segundo validador:{v}")
        regex = r"^(\+)[1-9][0-9\-\(\)\.]{9,15}$"
        if v and not re.search(regex, v, re.I):
            raise ValueError("Número de teléfono inválido.")
        return v

    class Config:
        orm_mode = True
        use_enum_values = True

A través de Postman, estoy enviando:

{
    "phone": "+917777777777"
}

Veo un error 400 en Postman:

[
    {
        "loc": [
            "phone",
            "phone"
        ],
        "msg": "campo requerido",
        "type": "value_error.missing"
    }
]

¿Algúna idea de qué estoy haciendo mal en lo anterior?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    En tu clase Phone, has definido un campo llamado phone con un tipo de str, pero en el método validator, estás intentando acceder a v.phone.get("phone"). Esto no funcionará porque v ya es el valor del campo phone, que es una cadena, y no puedes llamar al método get en una cadena.

    Para solucionarlo, puedes eliminar el campo phone de tu clase Phone y acceder al valor directamente en el método validator de la siguiente manera:

    class Phone(BaseModel):
        value: str
    
        @validator('value')
        def phone_validation(cls, v):
            regex = r"^(\+)[1-9][0-9\-\(\)\.]{9,15}$"
            if not re.search(regex, v, re.I):
                raise ValueError("Teléfono inválido.")
            return v
    
        class Config:
            orm_mode = True
    

    Y luego en tu clase UserPatchEntity, puedes usar este tipo personalizado Phone de la siguiente manera:

    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]
        role: Optional[RoleType]
    

    Ten en cuenta que cambié el nombre del campo de phone a value en la clase Phone, y actualicé el método validator para usar v en lugar de v.phone. También eliminé la opción use_enum_values de la clase Config, ya que no es necesaria en este caso.

Comments are closed.