I wanted to know what is the difference between:
from pydantic import BaseModel, Field class Person(BaseModel): name: str = Field(..., min_length=1)
from pydantic import BaseModel, constr class Person(BaseModel): name: constr(min_length=1)
Both seem to perform the same validation (even raise the exact same exception info when
name is an empty string). Is it just a matter of code style? Is one of them preferred over the other?
Also, if I wanted to include a list of nonempty strings as an attribute, which of these ways do you think would be better?:
from typing import List from pydantic import BaseModel, constr class Person(BaseModel): languages: List[constr(min_length=1)]
from typing import List from pydantic import BaseModel, Field class Person(BaseModel): languages: List[str] @validator('languages', each_item=True) def check_nonempty_strings(cls, v): if not v: raise ValueError('Empty string is not a valid language.') return v
FWIW, I am using this for a FastAPI app.
For my 2nd question, I think the first alternative is better, as it includes the length requirement in the Schema (and so it’s in the documentation)
constr and Fields don’t serve the same purpose.
constr is a specific type that give validation rules regarding this specific type. You have equivalent for all classic python types.
arguments of constr:
strip_whitespace: bool = False: removes leading and trailing whitespace to_lower: bool = False: turns all characters to lowercase strict: bool = False: controls type coercion min_length: int = None: minimum length of the string max_length: int = None: maximum length of the string curtail_length: int = None: shrinks the string length to the set value when it is longer than the set value regex: str = None: regex to validate the string against
As you can see thoses arguments allow you to manipulate the str itself not the behaviour of pydantic with this field.
Field doesn’t serve the same purpose, it’s a way of customizing fields, all fields not only str, it add 18 customization variables that you can find here.
Is it just a matter of code style? Is one of them preferred over the other?
for the specific case of str it is a matter of code style and what is preferred doesn’t matter, only your usecase does.
In general it is better to don’t mix different syntax toguether and since you often need Field(), you will find it often.
A classic use case would be api response that send json object in camelCase or PascalCase, you would use field alias to match thoses object and work with their variables in snake_case.
class Voice(BaseModel): name: str = Field(None, alias='ActorName') language_code: str = None mood: str = None
In your second question you could have used field to achive the same behaviour.
from typing import List from pydantic import BaseModel, Field class Person(BaseModel): languages: List[str] = Field(..., min_items=1)
If you want to learn more about limitation and field rules enforcement check this.
Answered By – Bastien B