A field validator is a Pydantic decorator that applies custom logic to one model field. It is useful when a field’s validity depends on runtime business data rather than a fixed type or pattern—for example, checking an ACH file’s immediate destination against routing numbers stored in a database. section 8.5.3
A practical field-validator workflow is:
- Attach @field_validator to the target field and define the validator as a class method. section 8.5.3
- Receive the field value, call a validation routine, and return it when the business rule succeeds. section 8.5.3
- Raise a clear ValueError when the value is invalid or when the external validation operation cannot complete. section 8.5.3
- Consider query frequency and update tests when validation changes which values are accepted. section 8.5.3
Normalizing an audit URL
An audit-log model can use Pydantic’s AnyUrl type for URL validation, then use a field validator in before mode to convert the validated value to a string before database insertion. This keeps storage compatibility inside the model instead of making every database caller perform the conversion. section 9.3.2
Listing 8.17 Pydantic field validator for immediate destination
@field_validator('immediate_destination') #1 @classmethod #2 def validate_immediate_destination(cls, v): try: if BankRoutingSql().valid_bank_routing_number(v): #2 return v #3 else: #3 raise ValueError('immediate_destination #3 ➥ is not a valid routing number') #3 except Exception: #4 raise ValueError('Unable to validate #4 ➥ immediate_destination') #4
Trace a database-backed validator that accepts an immediate destination only when the routing number is allowed, and distinguishes invalid values from validation failures. section 8.5.3
Listing 9.22 The AuditLogRecord class
class AuditLogRecord(BaseModel):
…
ip_address: Optional[IPvAnyNetwork] = Field( #1
None,
title="IP Address",
description="IP address from which the request originated.",
)
…
url: Optional[AnyUrl] = Field( #2
None,
title="URL",
description="URL accessed by the request.", max_length=255
)
…
@field_validator("url", mode="before") #3
@classmethod #3
def convert_url_to_str(cls, v: AnyUrl) -> str: #3
return str(v) #3
Compare field validation with pre-processing by converting an AnyUrl value to a database-compatible string inside the model. section 9.3.2
