Where possible pydantic uses standard library types to define fields, thus smoothing the learning curve. For many useful applications, however, no standard library type exists, so pydantic implements many commonly used types.
If no existing type suits your purpose you can also implement your own pydantic-compatible types with custom properties and validation.
pydantic supports many common types from the python standard library. If you need stricter processing see Strict Types; if you need to constrain the values allowed (e.g. to require a positive int) see Constrained Types.
bool
: see Booleans below for details on how bools are validated and what values are permitted
int
: pydantic uses int(v)
to coerce types to an int
;
see this warning on loss of information during data conversion
float
: similarly, float(v)
is used to coerce values to floats
str
: strings are accepted as-is, int
float
and Decimal
are coerced using str(v)
, bytes
and bytearray
are
converted using v.decode()
, enums inheriting from str
are converted using v.value
,
and all other types cause an error
bytes
: bytes
are accepted as-is, bytearray
is converted using bytes(v)
, str
are converted using v.encode()
,
and int
, float
, and Decimal
are coerced using str(v).encode()
list
: allows list
, tuple
, set
, frozenset
, deque
, or generators and casts to a list;
see typing.List
below for sub-type constraints
tuple
: allows list
, tuple
, set
, frozenset
, deque
, or generators and casts to a tuple;
see typing.Tuple
below for sub-type constraints
dict
: dict(v)
is used to attempt to convert a dictionary;
see typing.Dict
below for sub-type constraints
set
: allows list
, tuple
, set
, frozenset
, deque
, or generators and casts to a set;
see typing.Set
below for sub-type constraints
frozenset
: allows list
, tuple
, set
, frozenset
, deque
, or generators and casts to a frozen set;
see typing.FrozenSet
below for sub-type constraints
deque
: allows list
, tuple
, set
, frozenset
, deque
, or generators and casts to a deque;
see typing.Deque
below for sub-type constraints
namedtuple
: Same as tuple
but instantiates with the given namedtuple
!!! warning
pydantic doesn't validate the type of the fields inside the namedtuple
!
Even if you use typing.NamedTuple
and declare the expected types, pydantic will just
make sure you get an instance of namedtuple
.
Please use a BaseModel
or dataclass
if you expect validation
datetime.date
: see Datetime Types below for more detail on parsing and validation
datetime.time
: see Datetime Types below for more detail on parsing and validation
datetime.datetime
: see Datetime Types below for more detail on parsing and validation
datetime.timedelta
: see Datetime Types below for more detail on parsing and validation
typing.Any
: allows any value include None
, thus an Any
field is optional
typing.TypeVar
: constrains the values allowed based on constraints
or bound
, see TypeVar
typing.Union
: see Unions below for more detail on parsing and validation
typing.Optional
: Optional[x]
is simply short hand for Union[x, None]
;
see Unions below for more detail on parsing and validation and Required Fields for details about required fields that can receive None
as a value.
typing.List
: see Typing Iterables below for more detail on parsing and validation
typing.Tuple
: see Typing Iterables below for more detail on parsing and validation
typing.Dict
: see Typing Iterables below for more detail on parsing and validation
typing.Set
: see Typing Iterables below for more detail on parsing and validation
typing.FrozenSet
: see Typing Iterables below for more detail on parsing and validation
typing.Deque
: see Typing Iterables below for more detail on parsing and validation
typing.Sequence
: see Typing Iterables below for more detail on parsing and validation
typing.Iterable
: this is reserved for iterables that shouldn't be consumed. See Infinite Generators below for more detail on parsing and validation
typing.Type
: see Type below for more detail on parsing and validation
typing.Callable
: see Callable below for more detail on parsing and validation
typing.Pattern
: will cause the input value to be passed to re.compile(v)
to create a regex pattern
ipaddress.IPv4Address
: simply uses the type itself for validation by passing the value to IPv4Address(v)
;
see Pydantic Types for other custom IP address types
ipaddress.IPv4Interface
: simply uses the type itself for validation by passing the value to IPv4Address(v)
;
see Pydantic Types for other custom IP address types
ipaddress.IPv4Network
: simply uses the type itself for validation by passing the value to IPv4Network(v)
;
see Pydantic Types for other custom IP address types
ipaddress.IPv6Address
: simply uses the type itself for validation by passing the value to IPv6Address(v)
;
see Pydantic Types for other custom IP address types
ipaddress.IPv6Interface
: simply uses the type itself for validation by passing the value to IPv6Interface(v)
;
see Pydantic Types for other custom IP address types
ipaddress.IPv6Network
: simply uses the type itself for validation by passing the value to IPv6Network(v)
;
see Pydantic Types for other custom IP address types
enum.Enum
: checks that the value is a valid Enum instance
subclass of enum.Enum
: checks that the value is a valid member of the enum;
see Enums and Choices for more details
enum.IntEnum
: checks that the value is a valid IntEnum instance
subclass of enum.IntEnum
: checks that the value is a valid member of the integer enum;
see Enums and Choices for more details
decimal.Decimal
: pydantic attempts to convert the value to a string, then passes the string to Decimal(v)
pathlib.Path
: simply uses the type itself for validation by passing the value to Path(v)
;
see Pydantic Types for other more strict path types
uuid.UUID
: strings and bytes (converted to strings) are passed to UUID(v)
, with a fallback to UUID(bytes=v)
for bytes
and bytearray
;
see Pydantic Types for other stricter UUID types
ByteSize
: converts a bytes string with units to bytes
pydantic uses standard library typing
types as defined in PEP 484 to define complex objects.
{!.tmp_examples/types_iterables.py!}
(This script is complete, it should run "as is")
If you have a generator you can use Sequence
as described above. In that case, the
generator will be consumed and stored on the model as a list and its values will be
validated with the sub-type of Sequence
(e.g. int
in Sequence[int]
).
But if you have a generator that you don't want to be consumed, e.g. an infinite
generator or a remote data loader, you can define its type with Iterable
:
{!.tmp_examples/types_infinite_generator.py!}
(This script is complete, it should run "as is")
!!! warning
Iterable
fields only perform a simple check that the argument is iterable and
won't be consumed.
No validation of their values is performed as it cannot be done without consuming
the iterable.
!!! tip If you want to validate the values of an infinite generator you can create a separate model and use it while consuming the generator, reporting the validation errors as appropriate.
pydantic can't validate the values automatically for you because it would require
consuming the infinite generator.
You can create a validator to validate the first value in an infinite generator and still not consume it entirely.
{!.tmp_examples/types_infinite_generator_validate_first.py!}
(This script is complete, it should run "as is")
The Union
type allows a model attribute to accept different types, e.g.:
!!! warning This script is complete, it should run "as is". However, it may not reflect the desired behavior; see below.
{!.tmp_examples/types_union_incorrect.py!}
However, as can be seen above, pydantic will attempt to 'match' any of the types defined under Union
and will use
the first one that matches. In the above example the id
of user_03
was defined as a uuid.UUID
class (which
is defined under the attribute's Union
annotation) but as the uuid.UUID
can be marshalled into an int
it
chose to match against the int
type and disregarded the other types.
As such, it is recommended that, when defining Union
annotations, the most specific type is included first and
followed by less specific types. In the above example, the UUID
class should precede the int
and str
classes to preclude the unexpected representation as such:
{!.tmp_examples/types_union_correct.py!}
(This script is complete, it should run "as is")
!!! tip
The type Optional[x]
is a shorthand for Union[x, None]
.
`Optional[x]` can also be used to specify a required field that can take `None` as a value.
See more details in [Required Fields](models.md#required-fields).
pydantic uses python's standard enum
classes to define choices.
{!.tmp_examples/types_choices.py!}
(This script is complete, it should run "as is")
Pydantic supports the following datetime types:
-
datetime
fields can be:-
datetime
, existingdatetime
object -
int
orfloat
, assumed as Unix time, i.e. seconds (if >=-2e10
or <=2e10
) or milliseconds (if <-2e10
or >2e10
) since 1 January 1970 -
str
, following formats work:YYYY-MM-DD[T]HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]]]
int
orfloat
as a string (assumed as Unix time)
-
-
date
fields can be:-
date
, existingdate
object -
int
orfloat
, seedatetime
-
str
, following formats work:YYYY-MM-DD
int
orfloat
, seedatetime
-
-
time
fields can be:-
time
, existingtime
object -
str
, following formats work:HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]]]
-
-
timedelta
fields can be:-
timedelta
, existingtimedelta
object -
int
orfloat
, assumed as seconds -
str
, following formats work:[-][DD ][HH:MM]SS[.ffffff]
[±]P[DD]DT[HH]H[MM]M[SS]S
(ISO 8601 format for timedelta)
-
{!.tmp_examples/types_dt.py!}
!!! warning
The logic for parsing bool
fields has changed as of version v1.0.
Prior to **v1.0**, `bool` parsing never failed, leading to some unexpected results.
The new logic is described below.
A standard bool
field will raise a ValidationError
if the value is not one of the following:
- A valid boolean (i.e.
True
orFalse
), - The integers
0
or1
, - a
str
which when converted to lower case is one of'0', 'off', 'f', 'false', 'n', 'no', '1', 'on', 't', 'true', 'y', 'yes'
- a
bytes
which is valid (per the previous rule) when decoded tostr
!!! note
If you want stricter boolean logic (e.g. a field which only permits True
and False
) you can
use StrictBool
.
Here is a script demonstrating some of these behaviors:
{!.tmp_examples/types_boolean.py!}
(This script is complete, it should run "as is")
Fields can also be of type Callable
:
{!.tmp_examples/types_callable.py!}
(This script is complete, it should run "as is")
!!! warning Callable fields only perform a simple check that the argument is callable; no validation of arguments, their types, or the return type is performed.
pydantic supports the use of Type[T]
to specify that a field may only accept classes (not instances)
that are subclasses of T
.
{!.tmp_examples/types_type.py!}
(This script is complete, it should run "as is")
You may also use Type
to specify that any class is allowed.
{!.tmp_examples/types_bare_type.py!}
(This script is complete, it should run "as is")
TypeVar
is supported either unconstrained, constrained or with a bound.
{!.tmp_examples/types_typevar.py!}
(This script is complete, it should run "as is")
!!! note This is a new feature of the python standard library as of python 3.8; prior to python 3.8, it requires the typing-extensions package.
pydantic supports the use of typing.Literal
(or typing_extensions.Literal
prior to python 3.8)
as a lightweight way to specify that a field may accept only specific literal values:
{!.tmp_examples/types_literal1.py!}
(This script is complete, it should run "as is")
One benefit of this field type is that it can be used to check for equality with one or more specific values without needing to declare custom validators:
{!.tmp_examples/types_literal2.py!}
(This script is complete, it should run "as is")
With proper ordering in an annotated Union
, you can use this to parse types of decreasing specificity:
{!.tmp_examples/types_literal3.py!}
(This script is complete, it should run "as is")
pydantic also provides a variety of other useful types:
FilePath
: like Path
, but the path must exist and be a file
DirectoryPath
: like Path
, but the path must exist and be a directory
EmailStr
: requires email-validator to be installed;
the input string must be a valid email address, and the output is a simple string
NameEmail
: requires email-validator to be installed;
the input string must be either a valid email address or in the format Fred Bloggs <fred.bloggs@example.com>
,
and the output is a NameEmail
object which has two properties: name
and email
.
For Fred Bloggs <fred.bloggs@example.com>
the name would be "Fred Bloggs"
;
for fred.bloggs@example.com
it would be "fred.bloggs"
.
PyObject
: expects a string and loads the python object importable at that dotted path;
e.g. if 'math.cos'
was provided, the resulting field value would be the function cos
Color
: for parsing HTML and CSS colors; see Color Type
Json
: a special type wrapper which loads JSON before parsing; see JSON Type
PaymentCardNumber
: for parsing and validating payment cards; see payment cards
AnyUrl
: any URL; see URLs
AnyHttpUrl
: an HTTP URL; see URLs
HttpUrl
: a stricter HTTP URL; see URLs
PostgresDsn
: a postgres DSN style URL; see URLs
RedisDsn
: a redis DSN style URL; see URLs
stricturl
: a type method for arbitrary URL constraints; see URLs
UUID1
: requires a valid UUID of type 1; see UUID
above
UUID3
: requires a valid UUID of type 3; see UUID
above
UUID4
: requires a valid UUID of type 4; see UUID
above
UUID5
: requires a valid UUID of type 5; see UUID
above
SecretBytes
: bytes where the value is kept partially secret; see Secrets
SecretStr
: string where the value is kept partially secret; see Secrets
IPvAnyAddress
: allows either an IPv4Address
or an IPv6Address
IPvAnyInterface
: allows either an IPv4Interface
or an IPv6Interface
IPvAnyNetwork
: allows either an IPv4Network
or an IPv6Network
NegativeFloat
: allows a float which is negative; uses standard float
parsing then checks the value is less than 0;
see Constrained Types
NegativeInt
: allows an int which is negative; uses standard int
parsing then checks the value is less than 0;
see Constrained Types
PositiveFloat
: allows a float which is positive; uses standard float
parsing then checks the value is greater than 0;
see Constrained Types
PositiveInt
: allows an int which is positive; uses standard int
parsing then checks the value is greater than 0;
see Constrained Types
conbytes
: type method for constraining bytes;
see Constrained Types
condecimal
: type method for constraining Decimals;
see Constrained Types
confloat
: type method for constraining floats;
see Constrained Types
conint
: type method for constraining ints;
see Constrained Types
conlist
: type method for constraining lists;
see Constrained Types
conset
: type method for constraining sets;
see Constrained Types
constr
: type method for constraining strs;
see Constrained Types
For URI/URL validation the following types are available:
AnyUrl
: any scheme allowed, TLD not requiredAnyHttpUrl
: schemahttp
orhttps
, TLD not requiredHttpUrl
: schemahttp
orhttps
, TLD required, max length 2083PostgresDsn
: schemapostgres
orpostgresql
, user info required, TLD not requiredRedisDsn
: schemaredis
, user info not required, tld not required (CHANGED: user info not required from v1.6 onwards)stricturl
, method with the following keyword arguments:strip_whitespace: bool = True
min_length: int = 1
max_length: int = 2 ** 16
tld_required: bool = True
allowed_schemes: Optional[Set[str]] = None
The above types (which all inherit from AnyUrl
) will attempt to give descriptive errors when invalid URLs are
provided:
{!.tmp_examples/types_urls.py!}
(This script is complete, it should run "as is")
If you require a custom URI/URL type, it can be created in a similar way to the types defined above.
Assuming an input URL of http://samuel:pass@example.com:8000/the/path/?query=here#fragment=is;this=bit
,
the above types export the following properties:
-
scheme
: always set - the url schema (http
above) -
host
: always set - the url host (example.com
above) -
host_type
: always set - describes the type of host, either:domain
: e.g.example.com
,int_domain
: international domain, see below, e.g.exampl£e.org
,ipv4
: an IP V4 address, e.g.127.0.0.1
, oripv6
: an IP V6 address, e.g.2001:db8:ff00:42
-
user
: optional - the username if included (samuel
above) -
password
: optional - the password if included (pass
above) -
tld
: optional - the top level domain (com
above), Note: this will be wrong for any two-level domain, e.g. "co.uk". You'll need to implement your own list of TLDs if you require full TLD validation -
port
: optional - the port (8000
above) -
path
: optional - the path (/the/path/
above) -
query
: optional - the URL query (aka GET arguments or "search string") (query=here
above) -
fragment
: optional - the fragment (fragment=is;this=bit
above)
If further validation is required, these properties can be used by validators to enforce specific behaviour:
{!.tmp_examples/types_url_properties.py!}
(This script is complete, it should run "as is")
"International domains" (e.g. a URL where the host or TLD includes non-ascii characters) will be encoded via punycode (see this article for a good description of why this is important):
{!.tmp_examples/types_url_punycode.py!}
(This script is complete, it should run "as is")
!!! warning #### Underscores in Hostnames
In *pydantic* underscores are allowed in all parts of a domain except the tld.
Technically this might be wrong - in theory the hostname cannot have underscores, but subdomains can.
To explain this; consider the following two cases:
- `exam_ple.co.uk`: the hostname is `exam_ple`, which should not be allowed since it contains an underscore
- `foo_bar.example.com` the hostname is `example`, which should be allowed since the underscore is in the subdomain
Without having an exhaustive list of TLDs, it would be impossible to differentiate between these two. Therefore
underscores are allowed, but you can always do further validation in a validator if desired.
Also, Chrome, Firefox, and Safari all currently accept `http://exam_ple.com` as a URL, so we're in good
(or at least big) company.
You can use the Color
data type for storing colors as per
CSS3 specification. Colors can be defined via:
- name (e.g.
"Black"
,"azure"
) - hexadecimal value
(e.g.
"0x000"
,"#FFFFFF"
,"7fffd4"
) - RGB/RGBA tuples (e.g.
(255, 255, 255)
,(255, 255, 255, 0.5)
) - RGB/RGBA strings
(e.g.
"rgb(255, 255, 255)"
,"rgba(255, 255, 255, 0.5)"
) - HSL strings
(e.g.
"hsl(270, 60%, 70%)"
,"hsl(270, 60%, 70%, .5)"
)
{!.tmp_examples/types_color.py!}
(This script is complete, it should run "as is")
Color
has the following methods:
original
: the original string or tuple passed to Color
as_named
: returns a named CSS3 color; fails if the alpha channel is set or no such color exists unless
fallback=True
is supplied, in which case it falls back to as_hex
as_hex
: returns a string in the format #fff
or #ffffff
; will contain 4 (or 8) hex values if the alpha channel is set,
e.g. #7f33cc26
as_rgb
: returns a string in the format rgb(<red>, <green>, <blue>)
, or rgba(<red>, <green>, <blue>, <alpha>)
if the alpha channel is set
as_rgb_tuple
: returns a 3- or 4-tuple in RGB(a) format. The alpha
keyword argument can be used to define whether
the alpha channel should be included;
options: True
- always include, False
- never include, None
(default) - include if set
as_hsl
: string in the format hsl(<hue deg>, <saturation %>, <lightness %>)
or hsl(<hue deg>, <saturation %>, <lightness %>, <alpha>)
if the alpha channel is set
as_hsl_tuple
: returns a 3- or 4-tuple in HSL(a) format. The alpha
keyword argument can be used to define whether
the alpha channel should be included;
options: True
- always include, False
- never include, None
(the default) - include if set
The __str__
method for Color
returns self.as_named(fallback=True)
.
!!! note
the as_hsl*
refer to hue, saturation, lightness "HSL" as used in html and most of the world, not
"HLS" as used in python's colorsys
.
You can use the SecretStr
and the SecretBytes
data types for storing sensitive information
that you do not want to be visible in logging or tracebacks.
SecretStr
and SecretBytes
can be initialized idempotently or by using str
or bytes
literals respectively.
The SecretStr
and SecretBytes
will be formatted as either '**********'
or ''
on conversion to json.
{!.tmp_examples/types_secret_types.py!}
(This script is complete, it should run "as is")
You can use Json
data type to make pydantic first load a raw JSON string.
It can also optionally be used to parse the loaded object into another type base on
the type Json
is parameterised with:
{!.tmp_examples/types_json_type.py!}
(This script is complete, it should run "as is")
The PaymentCardNumber
type validates payment cards
(such as a debit or credit card).
{!.tmp_examples/types_payment_card_number.py!}
(This script is complete, it should run "as is")
PaymentCardBrand
can be one of the following based on the BIN:
PaymentCardBrand.amex
PaymentCardBrand.mastercard
PaymentCardBrand.visa
PaymentCardBrand.other
The actual validation verifies the card number is:
- a
str
of only digits - luhn valid
- the correct length based on the BIN, if Amex, Mastercard or Visa, and between 12 and 19 digits for all other brands
The value of numerous common types can be restricted using con*
type functions:
{!.tmp_examples/types_constrained.py!}
(This script is complete, it should run "as is")
Where Field
refers to the field function.
You can use the StrictStr
, StrictBytes
, StrictInt
, StrictFloat
, and StrictBool
types
to prevent coercion from compatible types.
These types will only pass validation when the validated value is of the respective type or is a subtype of that type.
This behavior is also exposed via the strict
field of the ConstrainedStr
, ConstrainedBytes
,
ConstrainedFloat
and ConstrainedInt
classes and can be combined with a multitude of complex validation rules.
The following caveats apply:
StrictBytes
(and thestrict
option ofConstrainedBytes
) will accept bothbytes
, andbytearray
types.StrictInt
(and thestrict
option ofConstrainedInt
) will not acceptbool
types, even thoughbool
is a subclass ofint
in Python. Other subclasses will work.StrictFloat
(and thestrict
option ofConstrainedFloat
) will not acceptint
.
{!.tmp_examples/types_strict.py!}
(This script is complete, it should run "as is")
You can use the ByteSize
data type to convert byte string representation to
raw bytes and print out human readable versions of the bytes as well.
!!! info
Note that 1b
will be parsed as "1 byte" and not "1 bit".
{!.tmp_examples/types_bytesize.py!}
(This script is complete, it should run "as is")
You can also define your own custom data types. There are several ways to achieve it.
You use a custom class with a classmethod __get_validators__
. It will be called
to get validators to parse and validate the input data.
!!! tip
These validators have the same semantics as in Validators, you can
declare a parameter config
, field
, etc.
{!.tmp_examples/types_custom_type.py!}
(This script is complete, it should run "as is")
Similar validation could be achieved using constr(regex=...)
except the value won't be
formatted with a space, the schema would just include the full pattern and the returned value would be a vanilla string.
See Schema for more details on how the model's schema is generated.
You can allow arbitrary types using the arbitrary_types_allowed
config in the
Model Config.
{!.tmp_examples/types_arbitrary_allowed.py!}
(This script is complete, it should run "as is")
!!! warning This is an advanced technique that you might not need in the beginning. In most of the cases you will probably be fine with standard pydantic models.
You can use
Generic Classes as
field types and perform custom validation based on the "type parameters" (or sub-types)
with __get_validators__
.
If the Generic class that you are using as a sub-type has a classmethod
__get_validators__
you don't need to use arbitrary_types_allowed
for it to work.
Because you can declare validators that receive the current field
, you can extract
the sub_fields
(from the generic class type parameters) and validate data with them.
{!.tmp_examples/types_generics.py!}
(This script is complete, it should run "as is")