Model Config
Behaviour of pydantic can be controlled via the Config
class on a model or a pydantic dataclass.
from pydantic import BaseModel, ValidationError
class Model(BaseModel):
v: str
class Config:
max_anystr_length = 10
error_msg_templates = {
'value_error.any_str.max_length': 'max_length:{limit_value}',
}
try:
Model(v='x' * 20)
except ValidationError as e:
print(e)
"""
1 validation error for Model
v
max_length:10 (type=value_error.any_str.max_length; limit_value=10)
"""
(This script is complete, it should run "as is")
Also, you can specify config options as model class kwargs:
from pydantic import BaseModel, ValidationError, Extra
class Model(BaseModel, extra=Extra.forbid):
a: str
try:
Model(a='spam', b='oh no')
except ValidationError as e:
print(e)
"""
1 validation error for Model
b
extra fields not permitted (type=value_error.extra)
"""
(This script is complete, it should run "as is")
Similarly, if using the @dataclass
decorator:
from datetime import datetime
from pydantic import ValidationError
from pydantic.dataclasses import dataclass
class MyConfig:
max_anystr_length = 10
validate_assignment = True
error_msg_templates = {
'value_error.any_str.max_length': 'max_length:{limit_value}',
}
@dataclass(config=MyConfig)
class User:
id: int
name: str = 'John Doe'
signup_ts: datetime = None
user = User(id='42', signup_ts='2032-06-21T12:00')
try:
user.name = 'x' * 20
except ValidationError as e:
print(e)
"""
1 validation error for User
name
max_length:10 (type=value_error.any_str.max_length; limit_value=10)
"""
(This script is complete, it should run "as is")
Options¶
title
- the title for the generated JSON Schema
anystr_strip_whitespace
- whether to strip leading and trailing whitespace for str & byte types (default:
False
) anystr_upper
- whether to make all characters uppercase for str & byte types (default:
False
) anystr_lower
- whether to make all characters lowercase for str & byte types (default:
False
) min_anystr_length
- the min length for str & byte types (default:
0
) max_anystr_length
- the max length for str & byte types (default:
None
) validate_all
- whether to validate field defaults (default:
False
) extra
- whether to ignore, allow, or forbid extra attributes during model initialization. Accepts the string values of
'ignore'
,'allow'
, or'forbid'
, or values of theExtra
enum (default:Extra.ignore
).'forbid'
will cause validation to fail if extra attributes are included,'ignore'
will silently ignore any extra attributes, and'allow'
will assign the attributes to the model. allow_mutation
- whether or not models are faux-immutable, i.e. whether
__setattr__
is allowed (default:True
)
frozen
Warning
This parameter is in beta
- setting
frozen=True
does everything thatallow_mutation=False
does, and also generates a__hash__()
method for the model. This makes instances of the model potentially hashable if all the attributes are hashable. (default:False
) use_enum_values
- whether to populate models with the
value
property of enums, rather than the raw enum. This may be useful if you want to serialisemodel.dict()
later (default:False
) fields
- a
dict
containing schema information for each field; this is equivalent to using theField
class, except when a field is already defined through annotation or the Field class, in which case onlyalias
,include
,exclude
,min_length
,max_length
,regex
,gt
,lt
,gt
,le
,multiple_of
,max_digits
,decimal_places
,min_items
,max_items
,unique_items
and allow_mutation can be set (for example you cannot set default of default_factory) (default:None
) validate_assignment
- whether to perform validation on assignment to attributes (default:
False
) allow_population_by_field_name
- whether an aliased field may be populated by its name as given by the model
attribute, as well as the alias (default:
False
)
Note
The name of this configuration setting was changed in v1.0 from
allow_population_by_alias
to allow_population_by_field_name
.
error_msg_templates
- a
dict
used to override the default error message templates. Pass in a dictionary with keys matching the error messages you want to override (default:{}
) arbitrary_types_allowed
- whether to allow arbitrary user types for fields (they are validated simply by
checking if the value is an instance of the type). If
False
,RuntimeError
will be raised on model declaration (default:False
). See an example in Field Types. orm_mode
- whether to allow usage of ORM mode
getter_dict
- a custom class (which should inherit from
GetterDict
) to use when decomposing arbitrary classes for validation, for use withorm_mode
; see Data binding. alias_generator
- a callable that takes a field name and returns an alias for it; see the dedicated section
keep_untouched
- a tuple of types (e.g. descriptors) for a model's default values that should not be changed during model creation and will not be included in the model schemas. Note: this means that attributes on the model with defaults of this type, not annotations of this type, will be left alone.
schema_extra
- a
dict
used to extend/update the generated JSON Schema, or a callable to post-process it; see schema customization json_loads
- a custom function for decoding JSON; see custom JSON (de)serialisation
json_dumps
- a custom function for encoding JSON; see custom JSON (de)serialisation
json_encoders
- a
dict
used to customise the way types are encoded to JSON; see JSON Serialisation underscore_attrs_are_private
- whether to treat any underscore non-class var attrs as private, or leave them as is; see Private model attributes
copy_on_model_validation
- string literal to control how models instances are processed during validation, with the following means (see #4093 for a full discussion of the changes to this field):
'none'
- models are not copied on validation, they're simply kept "untouched"'shallow'
- models are shallow copied, this is the default'deep'
- models are deep copied
smart_union
- whether pydantic should try to check all types inside
Union
to prevent undesired coercion; see the dedicated section post_init_call
- whether stdlib dataclasses
__post_init__
should be run before (default behaviour with value'before_validation'
) or after (value'after_validation'
) parsing and validation when they are converted. allow_inf_nan
- whether to allow infinity (
+inf
an-inf
) and NaN values to float fields, defaults toTrue
, set toFalse
for compatibility withJSON
, see #3994 for more details, added in V1.10
Change behaviour globally¶
If you wish to change the behaviour of pydantic globally, you can create your own custom BaseModel
with custom Config
since the config is inherited
from pydantic import BaseModel as PydanticBaseModel
class BaseModel(PydanticBaseModel):
class Config:
arbitrary_types_allowed = True
class MyClass:
"""A random class"""
class Model(BaseModel):
x: MyClass
(This script is complete, it should run "as is")
Alias Generator¶
If data source field names do not match your code style (e. g. CamelCase fields),
you can automatically generate aliases using alias_generator
:
from pydantic import BaseModel
def to_camel(string: str) -> str:
return ''.join(word.capitalize() for word in string.split('_'))
class Voice(BaseModel):
name: str
language_code: str
class Config:
alias_generator = to_camel
voice = Voice(Name='Filiz', LanguageCode='tr-TR')
print(voice.language_code)
#> tr-TR
print(voice.dict(by_alias=True))
#> {'Name': 'Filiz', 'LanguageCode': 'tr-TR'}
(This script is complete, it should run "as is")
Here camel case refers to "upper camel case" aka pascal case
e.g. CamelCase
. If you'd like instead to use lower camel case e.g. camelCase
,
instead use the to_lower_camel
function.
Alias Precedence¶
Warning
Alias priority logic changed in v1.4 to resolve buggy and unexpected behaviour in previous versions. In some circumstances this may represent a breaking change, see #1178 and the precedence order below for details.
In the case where a field's alias may be defined in multiple places, the selected value is determined as follows (in descending order of priority):
- Set via
Field(..., alias=<alias>)
, directly on the model - Defined in
Config.fields
, directly on the model - Set via
Field(..., alias=<alias>)
, on a parent model - Defined in
Config.fields
, on a parent model - Generated by
alias_generator
, regardless of whether it's on the model or a parent
Note
This means an alias_generator
defined on a child model does not take priority over an alias defined
on a field in a parent model.
For example:
from pydantic import BaseModel, Field
class Voice(BaseModel):
name: str = Field(None, alias='ActorName')
language_code: str = None
mood: str = None
class Character(Voice):
act: int = 1
class Config:
fields = {'language_code': 'lang'}
@classmethod
def alias_generator(cls, string: str) -> str:
# this is the same as `alias_generator = to_camel` above
return ''.join(word.capitalize() for word in string.split('_'))
print(Character.schema(by_alias=True))
"""
{
'title': 'Character',
'type': 'object',
'properties': {
'ActorName': {'title': 'Actorname', 'type': 'string'},
'lang': {'title': 'Lang', 'type': 'string'},
'Mood': {'title': 'Mood', 'type': 'string'},
'Act': {'title': 'Act', 'default': 1, 'type': 'integer'},
},
}
"""
(This script is complete, it should run "as is")
Smart Union¶
By default, as explained here, pydantic tries to validate (and coerce if it can) in the order of the Union
.
So sometimes you may have unexpected coerced data.
from typing import Union
from pydantic import BaseModel
class Foo(BaseModel):
pass
class Bar(BaseModel):
pass
class Model(BaseModel):
x: Union[str, int]
y: Union[Foo, Bar]
print(Model(x=1, y=Bar()))
#> x='1' y=Foo()
from pydantic import BaseModel
class Foo(BaseModel):
pass
class Bar(BaseModel):
pass
class Model(BaseModel):
x: str | int
y: Foo | Bar
print(Model(x=1, y=Bar()))
#> x='1' y=Foo()
(This script is complete, it should run "as is")
To prevent this, you can enable Config.smart_union
. Pydantic will then check all allowed types before even trying to coerce.
Know that this is of course slower, especially if your Union
is quite big.
from typing import Union
from pydantic import BaseModel
class Foo(BaseModel):
pass
class Bar(BaseModel):
pass
class Model(BaseModel):
x: Union[str, int]
y: Union[Foo, Bar]
class Config:
smart_union = True
print(Model(x=1, y=Bar()))
#> x=1 y=Bar()
from pydantic import BaseModel
class Foo(BaseModel):
pass
class Bar(BaseModel):
pass
class Model(BaseModel):
x: str | int
y: Foo | Bar
class Config:
smart_union = True
print(Model(x=1, y=Bar()))
#> x=1 y=Bar()
(This script is complete, it should run "as is")
Warning
Note that this option does not support compound types yet (e.g. differentiate List[int]
and List[str]
).
This option will be improved further once a strict mode is added in pydantic and will probably be the default behaviour in v2!
from typing import List, Union
from pydantic import BaseModel
class Model(BaseModel, smart_union=True):
x: Union[List[str], List[int]]
# Expected coercion
print(Model(x=[1, '2']))
#> x=['1', '2']
# Unexpected coercion
print(Model(x=[1, 2]))
#> x=['1', '2']
from typing import Union
from pydantic import BaseModel
class Model(BaseModel, smart_union=True):
x: Union[list[str], list[int]]
# Expected coercion
print(Model(x=[1, '2']))
#> x=['1', '2']
# Unexpected coercion
print(Model(x=[1, 2]))
#> x=['1', '2']
from pydantic import BaseModel
class Model(BaseModel, smart_union=True):
x: list[str] | list[int]
# Expected coercion
print(Model(x=[1, '2']))
#> x=['1', '2']
# Unexpected coercion
print(Model(x=[1, 2]))
#> x=['1', '2']
(This script is complete, it should run "as is")