Reputation: 918
I'm migrating a microservice from Pydantic 1 to Pydantic 2. Previously I had this:
class ComplementQuery(BaseModel):
imports: List[str] = Field(default_factory=list)
subquery: str = Field(...)
@validator("imports", pre=True, each_item=True)
def complement_imports(cls, value: str) -> str:
return f'import "{value}"'
I read the documentation and saw that @field_validator must now be used. Replace the validator and change the "pre=True" to "mode="Before". But the each_item I'm not sure how it should be addressed. Now I have something like this:
class ComplementQuery(BaseModel):
imports: List[Annotated[str, Field(default_factory=List)]]
subquery: str = Field(...)
@field_validator("imports", mode="before")
@classmethod
def complement_imports(cls, value: str) -> str:
return f'import "{value}"'
Will the complement_imports validator be applied to each of the imports items? Or should I put the BeforeValidator of pydantic.functional_validators in the Field? I am a little confused.
Maybe it should be something like this:
def complement_imports(v: str) -> str:
return f'import "{v}"'
class ComplementQuery(BaseModel):
imports: List[
Annotated[str, BeforeValidator(complement_imports), Field(default_factory=List)]
]
subquery: str = Field(...)
Upvotes: 1
Views: 1099
Reputation: 1648
I think the correct definition is the following:
from pydantic import BaseModel, Field, BeforeValidator
from typing import Annotated, List
def complement_imports(v: str) -> str:
return f'import "{v}"'
ImportItem = Annotated[str, BeforeValidator(complement_imports)]
class ComplementQuery(BaseModel):
imports: List[ImportItem] = Field(default_factory=list)
subquery: str = Field(...)
print(ComplementQuery(imports=["a", "b"], subquery="c"))
print(ComplementQuery(subquery="c"))
Which prints:
imports=['import "a"', 'import "b"'] subquery='c'
imports=[] subquery='c'
By defining the ImportItem
alias you simplify re-use. The default factory applies to the imports
field and not to the item, as in your example.
I hope this helps!
Upvotes: 0