Aller au contenu

Pydantic prend en charge de nombreux types courants de la bibliothèque standard Python. Si vous avez besoin d'un traitement plus strict, consultez Strict Types , y compris si vous devez limiter les valeurs autorisées (par exemple pour exiger un int positif).

Booléens

Un champ bool standard générera une ValidationError si la valeur n'est pas l'une des suivantes:

  • Un booléen valide (c'est-à-dire True ou False ),
  • Les entiers 0 ou 1 ,
  • une str qui, une fois convertie en minuscules, est l'une des '0', 'off', 'f', 'false', 'n', 'no', '1', 'on', 't', 'true', 'y', 'yes'
  • un bytes qui est valide selon la règle précédente lorsqu'il est décodé en str

!!! note Si vous souhaitez une logique booléenne plus stricte (par exemple un champ qui autorise uniquement True et False ), vous pouvez utiliser StrictBool .

Voici un script illustrant certains de ces comportements:

from pydantic import BaseModel, ValidationError


class BooleanModel(BaseModel):
    bool_value: bool


print(BooleanModel(bool_value=False))
#> bool_value=False
print(BooleanModel(bool_value='False'))
#> bool_value=False
print(BooleanModel(bool_value=1))
#> bool_value=True
try:
    BooleanModel(bool_value=[])
except ValidationError as e:
    print(str(e))
    """
    1 validation error for BooleanModel
    bool_value
      Input should be a valid boolean [type=bool_type, input_value=[], input_type=list]
    """

Types date/heure

Pydantic prend en charge les types datetime suivants:

datetime.datetime

  • Les champs datetime accepteront des valeurs de type:

    • datetime ; un objet datetime existant
    • int ou float ; supposé comme heure Unix, c'est-à-dire secondes (si >= -2e10 et <= 2e10 ) ou millisecondes (si < -2e10 ou > 2e10 ) depuis le 1er janvier 1970
    • str; les formats suivants sont acceptés :
      • YYYY-MM-DD[T]HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]
      • YYYY-MM-DD est accepté en mode laxiste, mais pas en mode strict
      • int ou float sous forme de chaîne (supposée à l'heure Unix)
    • datetime.date les instances sont acceptées en mode laxiste, mais pas en mode strict

    from datetime import datetime

    from pydantic import BaseModel

    class Event(BaseModel): dt: datetime = None

    event = Event(dt='2032-04-23T10:20:30.400+02:30')

    print(event.model_dump()) """ {'dt': datetime.datetime(2032, 4, 23, 10, 20, 30, 400000, tzinfo=TzInfo(+02:30))} """

datetime.date

  • les champs date accepteront des valeurs de type:

    • date ; un objet date existant
    • int ou float ; géré de la même manière que décrit pour datetime ci-dessus
    • str; les formats suivants sont acceptés :
      • YYYY-MM-DD
      • int ou float sous forme de chaîne (supposée à l'heure Unix)

    from datetime import date

    from pydantic import BaseModel

    class Birthday(BaseModel): d: date = None

    my_birthday = Birthday(d=1679616000.0)

    print(my_birthday.model_dump())

    >

datetime.time

  • les champs time accepteront des valeurs de type:

    • time ; un objet time existant
    • str; les formats suivants sont acceptés :
      • HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]

    from datetime import time

    from pydantic import BaseModel

    class Meeting(BaseModel): t: time = None

    m = Meeting(t=time(4, 8, 16))

    print(m.model_dump())

    >

datetime.timedelta

  • Les champs timedelta accepteront des valeurs de type:

    • timedelta; un objet timedelta existant
    • int ou float ; supposé être des secondes
    • str; les formats suivants sont acceptés :
      • [-][DD]D[,][HH:MM:]SS[.ffffff]
        • Ex : '1d,01:02:03.000004' ou '1D01:02:03.000004' ou '01:02:03'
      • [±]P[DD]DT[HH]H[MM]M[SS]S (format ISO 8601 pour timedelta)

    from datetime import timedelta

    from pydantic import BaseModel

    class Model(BaseModel): td: timedelta = None

    m = Model(td='P3DT12H30M5S')

    print(m.model_dump())

    >

Types de nombres

Pydantic prend en charge les types numériques suivants de la bibliothèque standard Python:

int

  • Pydantic utilise int(v) pour contraindre les types à un int ; voir Conversion de données pour plus de détails sur la perte d'informations lors de la conversion de données.

float

  • Pydantic utilise float(v) pour contraindre les valeurs à flotter.

enum.IntEnum

  • Validation: Pydantic vérifie que la valeur est une instance IntEnum valide.
  • Validation pour la sous-classe d' enum.IntEnum: vérifie que la valeur est un membre valide de l'énumération entière; voir Énumérations et choix pour plus de détails.

decimal.Decimal

  • Validation: Pydantic tente de convertir la valeur en chaîne, puis transmet la chaîne à Decimal(v) .
  • Sérialisation: Pydantic sérialise les types Decimal sous forme de chaînes. Vous pouvez utiliser un sérialiseur personnalisé pour remplacer ce comportement si vous le souhaitez. Par exemple:

    from decimal import Decimal

    from typing_extensions import Annotated

    from pydantic import BaseModel, PlainSerializer

    class Model(BaseModel): x: Decimal y: Annotated[ Decimal, PlainSerializer( lambda x: float(x), return_type=float, when_used='json' ), ]

    my_model = Model(x=Decimal('1.1'), y=Decimal('2.1'))

    print(my_model.model_dump()) # (1)!

    >

    print(my_model.model_dump(mode='json')) # (2)!

    >

    print(my_model.model_dump_json()) # (3)!

    >

  • En utilisant model_dump, x et y restent des instances du type Decimal

  • En utilisant model_dump avec mode='json' , x est sérialisé en tant que string et y est sérialisé en tant que float en raison du sérialiseur personnalisé appliqué.
  • En utilisant model_dump_json, x est sérialisé en tant que string et y est sérialisé en tant que float en raison du sérialiseur personnalisé appliqué.

Enum

Pydantic utilise les classes standard enum de Python pour définir des choix.

enum.Enum vérifie que la valeur est une instance Enum valide. La sous-classe de enum.Enum vérifie que la valeur est un membre valide de l'énumération.

from enum import Enum, IntEnum

from pydantic import BaseModel, ValidationError


class FruitEnum(str, Enum):
    pear = 'pear'
    banana = 'banana'


class ToolEnum(IntEnum):
    spanner = 1
    wrench = 2


class CookingModel(BaseModel):
    fruit: FruitEnum = FruitEnum.pear
    tool: ToolEnum = ToolEnum.spanner


print(CookingModel())
#> fruit=<FruitEnum.pear: 'pear'> tool=<ToolEnum.spanner: 1>
print(CookingModel(tool=2, fruit='banana'))
#> fruit=<FruitEnum.banana: 'banana'> tool=<ToolEnum.wrench: 2>
try:
    CookingModel(fruit='other')
except ValidationError as e:
    print(e)
    """
    1 validation error for CookingModel
    fruit
      Input should be 'pear' or 'banana' [type=enum, input_value='other', input_type=str]
    """

Listes et tuples

list

Autorise list, tuple, set, frozenset, deque ou des générateurs et des conversions en list. Lorsqu'un paramètre générique est fourni, la validation appropriée est appliquée à tous les éléments de la liste.

typing.List

Géré de la même manière que list ci-dessus.

from typing import List, Optional

from pydantic import BaseModel


class Model(BaseModel):
    simple_list: Optional[list] = None
    list_of_ints: Optional[List[int]] = None


print(Model(simple_list=['1', '2', '3']).simple_list)
#> ['1', '2', '3']
print(Model(list_of_ints=['1', '2', '3']).list_of_ints)
#> [1, 2, 3]

tuple

Autorise list, tuple, set, frozenset, deque ou des générateurs et convertit en un tuple. Lorsque des paramètres génériques sont fournis, la validation appropriée est appliquée aux éléments respectifs du tuple

typing.Tuple

Géré de la même manière que tuple ci-dessus.

from typing import Optional, Tuple

from pydantic import BaseModel


class Model(BaseModel):
    simple_tuple: Optional[tuple] = None
    tuple_of_different_types: Optional[Tuple[int, float, bool]] = None


print(Model(simple_tuple=[1, 2, 3, 4]).simple_tuple)
#> (1, 2, 3, 4)
print(Model(tuple_of_different_types=[3, 2, 1]).tuple_of_different_types)
#> (3, 2.0, True)

typing.NamedTuple

Les sous-classes de typing.NamedTuple sont similaires à tuple , mais créent des instances de la classe namedtuple nommée.

Les sous-classes de collections.namedtuple sont similaires à la sous-classe de typing.NamedTuple, mais comme les types de champs ne sont pas spécifiés, tous les champs sont traités comme ayant le type Any.

from typing import NamedTuple

from pydantic import BaseModel, ValidationError


class Point(NamedTuple):
    x: int
    y: int


class Model(BaseModel):
    p: Point


try:
    Model(p=('1.3', '2'))
except ValidationError as e:
    print(e)
    """
    1 validation error for Model
    p.0
      Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='1.3', input_type=str]
    """

Déqué

deque

Autorise list, tuple, set, frozenset, deque ou des générateurs et des conversions en deque. Lorsque des paramètres génériques sont fournis, la validation appropriée est appliquée aux éléments respectifs du deque .

typing.Deque

Géré de la même manière que deque ci-dessus.

from typing import Deque, Optional

from pydantic import BaseModel


class Model(BaseModel):
    deque: Optional[Deque[int]] = None


print(Model(deque=[1, 2, 3]).deque)
#> deque([1, 2, 3])

Ensembles

set

Autorise list, tuple, set, frozenset, deque ou des générateurs et des conversions en un set. Lorsqu'un paramètre générique est fourni, la validation appropriée est appliquée à tous les éléments de l'ensemble.

typing.Set

Géré de la même manière que set -dessus.

from typing import Optional, Set

from pydantic import BaseModel


class Model(BaseModel):
    simple_set: Optional[set] = None
    set_of_ints: Optional[Set[int]] = None


print(Model(simple_set={'1', '2', '3'}).simple_set)
#> {'1', '2', '3'}
print(Model(simple_set=['1', '2', '3']).simple_set)
#> {'1', '2', '3'}
print(Model(set_of_ints=['1', '2', '3']).set_of_ints)
#> {1, 2, 3}

frozenset

Autorise list, tuple, set, frozenset, deque ou des générateurs et des conversions vers un frozenset. Lorsqu'un paramètre générique est fourni, la validation appropriée est appliquée à tous les éléments de l'ensemble figé.

typing.FrozenSet

Géré de la même manière que frozenset ci-dessus.

from typing import FrozenSet, Optional

from pydantic import BaseModel


class Model(BaseModel):
    simple_frozenset: Optional[frozenset] = None
    frozenset_of_ints: Optional[FrozenSet[int]] = None


m1 = Model(simple_frozenset=['1', '2', '3'])
print(type(m1.simple_frozenset))
#> <class 'frozenset'>
print(sorted(m1.simple_frozenset))
#> ['1', '2', '3']

m2 = Model(frozenset_of_ints=['1', '2', '3'])
print(type(m2.frozenset_of_ints))
#> <class 'frozenset'>
print(sorted(m2.frozenset_of_ints))
#> [1, 2, 3]

Autres itérables

typing.Sequence

Ceci est destiné à être utilisé lorsque la valeur fournie doit répondre aux exigences de la Sequence ABC et qu'il est souhaitable de procéder à une validation rapide des valeurs dans le conteneur. Notez que lorsque la validation doit être effectuée sur les valeurs du conteneur, le type du conteneur peut ne pas être conservé puisque la validation peut finir par remplacer des valeurs. Nous garantissons que la valeur validée sera un typing.Sequence valide, mais elle peut avoir un type différent de celui fourni (généralement, elle deviendra une list ).

typing.Iterable

Ceci est destiné à être utilisé lorsque la valeur fournie peut être un itérable qui ne doit pas être consommé. Voir Générateurs infinis ci-dessous pour plus de détails sur l'analyse et la validation. Semblable à typing.Sequence, nous garantissons que le résultat validé sera un typing.Iterable valide, mais il peut avoir un type différent de celui fourni. En particulier, même si un type non générateur tel qu'une list est fourni, la valeur post-validation d'un champ de type typing.Iterable sera un générateur.

Voici un exemple simple utilisant typing.Sequence:

from typing import Sequence

from pydantic import BaseModel


class Model(BaseModel):
    sequence_of_ints: Sequence[int] = None


print(Model(sequence_of_ints=[1, 2, 3, 4]).sequence_of_ints)
#> [1, 2, 3, 4]
print(Model(sequence_of_ints=(1, 2, 3, 4)).sequence_of_ints)
#> (1, 2, 3, 4)

Générateurs infinis

Si vous souhaitez valider un générateur, vous pouvez toujours utiliser Sequence comme décrit ci-dessus. Dans ce cas, le générateur sera consommé et stocké sur le modèle sous forme de liste et ses valeurs seront validées par rapport au paramètre de type de la Sequence (par exemple int dans Sequence[int] ).

Cependant, si vous disposez d'un générateur que vous ne souhaitez pas utiliser avec impatience (par exemple un générateur infini ou un chargeur de données distant), vous pouvez utiliser un champ de type Iterable:

from typing import Iterable

from pydantic import BaseModel


class Model(BaseModel):
    infinite: Iterable[int]


def infinite_ints():
    i = 0
    while True:
        yield i
        i += 1


m = Model(infinite=infinite_ints())
print(m)
"""
infinite=ValidatorIterator(index=0, schema=Some(Int(IntValidator { strict: false })))
"""

for i in m.infinite:
    print(i)
    #> 0
    #> 1
    #> 2
    #> 3
    #> 4
    #> 5
    #> 6
    #> 7
    #> 8
    #> 9
    #> 10
    if i == 10:
        break

!!! avertissement Lors de la validation initiale, les champs Iterable effectuent uniquement une simple vérification que l'argument fourni est itérable. Pour éviter qu'il ne soit consommé, aucune validation des valeurs fournies n'est effectuée avec impatience.

Bien que les valeurs générées ne soient pas validées avec impatience, elles sont toujours validées lorsqu'elles sont générées et déclencheront une ValidationError au moment du rendement, le cas échéant:

from typing import Iterable

from pydantic import BaseModel, ValidationError


class Model(BaseModel):
    int_iterator: Iterable[int]


def my_iterator():
    yield 13
    yield '27'
    yield 'a'


m = Model(int_iterator=my_iterator())
print(next(m.int_iterator))
#> 13
print(next(m.int_iterator))
#> 27
try:
    next(m.int_iterator)
except ValidationError as e:
    print(e)
    """
    1 validation error for ValidatorIterator
    2
      Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='a', input_type=str]
    """

Types de mappage

dict

dict(v) est utilisé pour tenter de convertir un dictionnaire. voir typing.Dict ci-dessous pour les contraintes de sous-type.

from pydantic import BaseModel, ValidationError


class Model(BaseModel):
    x: dict


m = Model(x={'foo': 1})
print(m.model_dump())
#> {'x': {'foo': 1}}

try:
    Model(x='test')
except ValidationError as e:
    print(e)
    """
    1 validation error for Model
    x
      Input should be a valid dictionary [type=dict_type, input_value='test', input_type=str]
    """

typing.Dict

from typing import Dict

from pydantic import BaseModel, ValidationError


class Model(BaseModel):
    x: Dict[str, int]


m = Model(x={'foo': 1})
print(m.model_dump())
#> {'x': {'foo': 1}}

try:
    Model(x={'foo': '1'})
except ValidationError as e:
    print(e)
    """
    1 validation error for Model
    x
      Input should be a valid dictionary [type=dict_type, input_value='test', input_type=str]
    """

TypéDict

!!! note Il s'agit d'une nouvelle fonctionnalité de la bibliothèque standard Python à partir de Python 3.8. En raison des limitations de typing.TypedDict avant la version 3.12, le package typing-extensions est requis pour Python <3.12. Vous devrez importer TypedDict depuis typing_extensions au lieu de typing et vous obtiendrez une erreur de temps de construction si vous ne le faites pas.

TypedDict déclare un type de dictionnaire qui s'attend à ce que toutes ses instances aient un certain ensemble de clés, où chaque clé est associée à une valeur d'un type cohérent.

C'est la même chose que dict mais Pydantic validera le dictionnaire puisque les clés sont annotées.

from typing_extensions import TypedDict

from pydantic import TypeAdapter, ValidationError


class User(TypedDict):
    name: str
    id: int


ta = TypeAdapter(User)

print(ta.validate_python({'name': 'foo', 'id': 1}))
#> {'name': 'foo', 'id': 1}

try:
    ta.validate_python({'name': 'foo'})
except ValidationError as e:
    print(e)
    """
    1 validation error for typed-dict
    id
      Field required [type=missing, input_value={'name': 'foo'}, input_type=dict]
    """

Vous pouvez définir __pydantic_config__ pour modifier le modèle hérité de TypedDict. Voir la référence de l'API ConfigDict pour plus de détails.

from typing import Optional

from typing_extensions import TypedDict

from pydantic import ConfigDict, TypeAdapter, ValidationError


# `total=False` means keys are non-required
class UserIdentity(TypedDict, total=False):
    name: Optional[str]
    surname: str


class User(TypedDict):
    __pydantic_config__ = ConfigDict(extra='forbid')

    identity: UserIdentity
    age: int


ta = TypeAdapter(User)

print(
    ta.validate_python(
        {'identity': {'name': 'Smith', 'surname': 'John'}, 'age': 37}
    )
)
#> {'identity': {'name': 'Smith', 'surname': 'John'}, 'age': 37}

print(
    ta.validate_python(
        {'identity': {'name': None, 'surname': 'John'}, 'age': 37}
    )
)
#> {'identity': {'name': None, 'surname': 'John'}, 'age': 37}

print(ta.validate_python({'identity': {}, 'age': 37}))
#> {'identity': {}, 'age': 37}


try:
    ta.validate_python(
        {'identity': {'name': ['Smith'], 'surname': 'John'}, 'age': 24}
    )
except ValidationError as e:
    print(e)
    """
    1 validation error for typed-dict
    identity.name
      Input should be a valid string [type=string_type, input_value=['Smith'], input_type=list]
    """

try:
    ta.validate_python(
        {
            'identity': {'name': 'Smith', 'surname': 'John'},
            'age': '37',
            'email': 'john.smith@me.com',
        }
    )
except ValidationError as e:
    print(e)
    """
    1 validation error for typed-dict
    email
      Extra inputs are not permitted [type=extra_forbidden, input_value='john.smith@me.com', input_type=str]
    """

Appelable

Voir ci-dessous pour plus de détails sur l'analyse et la validation

Les champs peuvent également être de type Callable:

from typing import Callable

from pydantic import BaseModel


class Foo(BaseModel):
    callback: Callable[[int], int]


m = Foo(callback=lambda x: x)
print(m)
#> callback=<function <lambda> at 0x0123456789ab>

!!! avertissement Les champs appelables effectuent uniquement une simple vérification que l'argument est appelable; aucune validation des arguments, de leurs types ou du type de retour n'est effectuée.

Types d'adresses IP

  • ipaddress.IPv4Address: utilise le type lui-même pour la validation en transmettant la valeur à IPv4Address(v) .
  • ipaddress.IPv4Interface: utilise le type lui-même pour la validation en transmettant la valeur à IPv4Address(v) .
  • ipaddress.IPv4Network: utilise le type lui-même pour la validation en transmettant la valeur à IPv4Network(v) .
  • ipaddress.IPv6Address: utilise le type lui-même pour la validation en transmettant la valeur à IPv6Address(v) .
  • ipaddress.IPv6Interface: utilise le type lui-même pour la validation en transmettant la valeur à IPv6Interface(v) .
  • ipaddress.IPv6Network: utilise le type lui-même pour la validation en transmettant la valeur à IPv6Network(v) .

Voir Types de réseau pour d'autres types d'adresses IP personnalisées.

UUID

Pour UUID, Pydantic essaie d'utiliser le type lui-même pour la validation en transmettant la valeur à UUID(v) . Il existe une solution de repli vers UUID(bytes=v) pour bytes et bytearray .

Si vous souhaitez contraindre la version de l'UUID, vous pouvez vérifier les types suivants:

  • UUID1: nécessite la version 1 de l'UUID.
  • UUID3: nécessite la version 3 de l'UUID.
  • UUID4: nécessite la version 4 de l'UUID.
  • UUID5: nécessite la version 5 de l'UUID.

Union

Pydantic prend en charge largement la validation des unions, à la fois typing.Union et la syntaxe des tuyaux de Python 3.10 ( A | B ) sont prises en charge. Pour en savoir plus, consultez la section Unions de la documentation sur les concepts.

Type et TypeVar

type

Pydantic prend en charge l'utilisation de type[T] pour spécifier qu'un champ ne peut accepter que des classes (et non des instances) qui sont des sous-classes de T .

typing.Type

Géré de la même manière que type ci-dessus.

from typing import Type

from pydantic import BaseModel, ValidationError


class Foo:
    pass


class Bar(Foo):
    pass


class Other:
    pass


class SimpleModel(BaseModel):
    just_subclasses: Type[Foo]


SimpleModel(just_subclasses=Foo)
SimpleModel(just_subclasses=Bar)
try:
    SimpleModel(just_subclasses=Other)
except ValidationError as e:
    print(e)
    """
    1 validation error for SimpleModel
    just_subclasses
      Input should be a subclass of Foo [type=is_subclass_of, input_value=<class '__main__.Other'>, input_type=type]
    """

Vous pouvez également utiliser Type pour spécifier que n'importe quelle classe est autorisée.

from typing import Type

from pydantic import BaseModel, ValidationError


class Foo:
    pass


class LenientSimpleModel(BaseModel):
    any_class_goes: Type


LenientSimpleModel(any_class_goes=int)
LenientSimpleModel(any_class_goes=Foo)
try:
    LenientSimpleModel(any_class_goes=Foo())
except ValidationError as e:
    print(e)
    """
    1 validation error for LenientSimpleModel
    any_class_goes
      Input should be a type [type=is_type, input_value=<__main__.Foo object at 0x0123456789ab>, input_type=Foo]
    """

typing.TypeVar

TypeVar est pris en charge sans contrainte, avec contrainte ou avec une limite.

from typing import TypeVar

from pydantic import BaseModel

Foobar = TypeVar('Foobar')
BoundFloat = TypeVar('BoundFloat', bound=float)
IntStr = TypeVar('IntStr', int, str)


class Model(BaseModel):
    a: Foobar  # equivalent of ": Any"
    b: BoundFloat  # equivalent of ": float"
    c: IntStr  # equivalent of ": Union[int, str]"


print(Model(a=[1], b=4.2, c='x'))
#> a=[1] b=4.2 c='x'

# a may be None
print(Model(a=None, b=1, c=1))
#> a=None b=1.0 c=1

Aucun type

None, type(None) ou Literal[None] sont tous équivalents selon la spécification de typage . Autorise uniquement la valeur None .

Cordes

str : Les chaînes sont acceptées telles quelles. bytes et bytearray sont convertis à l'aide de v.decode() . Les Enum s inheriting from str are converted using v.value`. Tous les autres types provoquent une erreur.

Les chaînes ne sont pas des séquences

While instances of str are technically valid instances of the Sequence[str] protocol from a type-checker's point of view, this is frequently not intended as is a common source of bugs.

As a result, Pydantic raises a ValidationError if you attempt to pass a str or bytes instance into a field of type Sequence[str] or Sequence[bytes]:

from typing import Optional, Sequence

from pydantic import BaseModel, ValidationError

class Model(BaseModel): sequence_of_strs: Optional[Sequence[str]] = None sequence_of_bytes: Optional[Sequence[bytes]] = None

print(Model(sequence_of_strs=['a', 'bc']).sequence_of_strs)

> ['a', 'bc']

print(Model(sequence_of_strs=('a', 'bc')).sequence_of_strs)

> ('a', 'bc')

print(Model(sequence_of_bytes=[b'a', b'bc']).sequence_of_bytes)

> [b'a', b'bc']

print(Model(sequence_of_bytes=(b'a', b'bc')).sequence_of_bytes)

> (b'a', b'bc')

try: Model(sequence_of_strs='abc') except ValidationError as e: print(e) """ 1 validation error for Model sequence_of_strs 'str' instances are not allowed as a Sequence value [type=sequence_str, input_value='abc', input_type=str] """ try: Model(sequence_of_bytes=b'abc') except ValidationError as e: print(e) """ 1 validation error for Model sequence_of_bytes 'bytes' instances are not allowed as a Sequence value [type=sequence_str, input_value=b'abc', input_type=bytes] """

Octets

bytes sont acceptés tels quels. bytearray est converti en utilisant bytes(v) . str sont convertis en utilisant v.encode() . int , float et Decimal sont contraints à l'aide de str(v).encode() . Voir ByteSize pour plus de détails.

typing.Literal

Pydantic prend en charge l'utilisation de typing.Literal comme moyen léger de spécifier qu'un champ ne peut accepter que des valeurs littérales spécifiques:

from typing import Literal

from pydantic import BaseModel, ValidationError


class Pie(BaseModel):
    flavor: Literal['apple', 'pumpkin']


Pie(flavor='apple')
Pie(flavor='pumpkin')
try:
    Pie(flavor='cherry')
except ValidationError as e:
    print(str(e))
    """
    1 validation error for Pie
    flavor
      Input should be 'apple' or 'pumpkin' [type=literal_error, input_value='cherry', input_type=str]
    """

L'un des avantages de ce type de champ est qu'il peut être utilisé pour vérifier l'égalité avec une ou plusieurs valeurs spécifiques sans avoir besoin de déclarer des validateurs personnalisés:

from typing import ClassVar, List, Literal, Union

from pydantic import BaseModel, ValidationError


class Cake(BaseModel):
    kind: Literal['cake']
    required_utensils: ClassVar[List[str]] = ['fork', 'knife']


class IceCream(BaseModel):
    kind: Literal['icecream']
    required_utensils: ClassVar[List[str]] = ['spoon']


class Meal(BaseModel):
    dessert: Union[Cake, IceCream]


print(type(Meal(dessert={'kind': 'cake'}).dessert).__name__)
#> Cake
print(type(Meal(dessert={'kind': 'icecream'}).dessert).__name__)
#> IceCream
try:
    Meal(dessert={'kind': 'pie'})
except ValidationError as e:
    print(str(e))
    """
    2 validation errors for Meal
    dessert.Cake.kind
      Input should be 'cake' [type=literal_error, input_value='pie', input_type=str]
    dessert.IceCream.kind
      Input should be 'icecream' [type=literal_error, input_value='pie', input_type=str]
    """

Avec un classement approprié dans un Union annoté, vous pouvez l'utiliser pour analyser les types de spécificité décroissante:

from typing import Literal, Optional, Union

from pydantic import BaseModel


class Dessert(BaseModel):
    kind: str


class Pie(Dessert):
    kind: Literal['pie']
    flavor: Optional[str]


class ApplePie(Pie):
    flavor: Literal['apple']


class PumpkinPie(Pie):
    flavor: Literal['pumpkin']


class Meal(BaseModel):
    dessert: Union[ApplePie, PumpkinPie, Pie, Dessert]


print(type(Meal(dessert={'kind': 'pie', 'flavor': 'apple'}).dessert).__name__)
#> ApplePie
print(type(Meal(dessert={'kind': 'pie', 'flavor': 'pumpkin'}).dessert).__name__)
#> PumpkinPie
print(type(Meal(dessert={'kind': 'pie'}).dessert).__name__)
#> Dessert
print(type(Meal(dessert={'kind': 'cake'}).dessert).__name__)
#> Dessert

typing.Any

Autorise n’importe quelle valeur, y compris None .

typing.Annotated

Permet d'encapsuler un autre type avec des métadonnées arbitraires, conformément au PEP-593 . L'indice Annotated peut contenir un seul appel à la fonction Field , mais sinon, les métadonnées supplémentaires sont ignorées et le type racine est utilisé.

typing.Pattern

La valeur d'entrée sera transmise à re.compile(v) pour créer un modèle d'expression régulière.

pathlib.Path

Utilise simplement le type lui-même pour la validation en passant la valeur à Path(v) .


本文总阅读量