pythonpydanticpydantic-v2

pydantic model validator raise ValueError to field


I am trying to do a validation on passwords where if they dont match, return an error. But I want to assign the error to field.

class RequestFile(
    BaseModel
):
    password: str = Field(..., min_length=8, max_length=128)
    confirm_password: str = Field(..., min_length=8, max_length=128)

    @field_validator("password")
    def password_validate(cls, v: str) -> str:
        if not v.strip():
            raise ValueError("Password required")
        return v

    @field_validator("confirm_password")
    def confirm_password_validate(cls, v: str) -> str:
        if not v.strip():
            raise ValueError("Confirm Password Required")
        return v

    @model_validator(mode="before")
    def check_passwords_match(cls, values):
        password = values.get("password")
        confirm_password = values.get("confirm_password")

        if password != confirm_password:
            raise ValueError("Passwords does not match")

        return values

In the code above, when either password or confirm_password failed validation (char length), it pushes the ValueError to field password and confirm_password respectively. However, when they dont match, it returns the ValueError but not on any field. How to push the ValueError to either password or confirm_password? Preferrably in confirm_password


Solution

  • There is an example in the official documentation.

    To explain briefly, after-validators can access parsed fields via the info argument.

    from pydantic import BaseModel, Field, field_validator
    from pydantic_core.core_schema import ValidationInfo
    
    
    class RequestFile(BaseModel):
        password: str = Field(..., min_length=8, max_length=128)
        confirm_password: str = Field(..., min_length=8, max_length=128)
    
        @field_validator("password")
        @classmethod
        def password_validate(cls, v: str) -> str:
            if not v.strip():
                raise ValueError("Password required")
            return v
    
        @field_validator("confirm_password")
        @classmethod
        def confirm_password_validate(cls, v: str) -> str:
            if not v.strip():
                raise ValueError("Confirm Password Required")
            return v
    
        @field_validator("confirm_password", mode="after")
        @classmethod
        def check_passwords_match(cls, value: str, info: ValidationInfo) -> str:
            if value != info.data["password"]:
                raise ValueError("Passwords do not match")
            return value
    
    
    RequestFile(
        password="password123",
        confirm_password="password12",
    )
    
    pydantic_core._pydantic_core.ValidationError: 1 validation error for RequestFile
    confirm_password
      Value error, Passwords do not match [type=value_error, input_value='password12', input_type=str]
        For further information visit https://errors.pydantic.dev/2.11/v/value_error