Source: Pydantic

← Rendered

markdown source:

---
description: Pydantic - библиотека для валидации типов в python
title: Pydantic
tags: pydantic pip data-bases python
---
Типизация для python [Документация](https://pydantic-docs.helpmanual.io/). Использует [[type-annotation]] на базе [[mypy]]

```python
from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel


class User(BaseModel):
    id: int
    name = 'John Doe'
    signup_ts: Optional[datetime] = None
    friends: List[int] = []


external_data = {
    'id': '123',
    'signup_ts': '2019-06-01 12:22',
    'friends': [1, 2, '3'],
}
user = User(**external_data)
print(user.id)
#> 123
print(repr(user.signup_ts))
#> datetime.datetime(2019, 6, 1, 12, 22)
print(user.friends)
#> [1, 2, 3]
print(user.dict())
"""
{
    'id': 123,
    'signup_ts': datetime.datetime(2019, 6, 1, 12, 22),
    'friends': [1, 2, 3],
    'name': 'John Doe',
}
"""
```

## Установка

`pip install pydantic`

Три варианта

`pip install pydantic[email]` [валидация имейлов](https://github.com/JoshData/python-email-validator)
`pip install pydantic[dotenv]` [.env support](https://pydantic-docs.helpmanual.io/usage/settings/#dotenv-env-support) - [[.env-переменные-окружения]]
`pip install pydantic[email,dotenv]`

## Использование

### Модели

```python
from pydantic import BaseModel

class User(BaseModel):
    id: int
    name = 'Jane Doe'
```

Каждый класс модели наследует базовой модели pydantic. В данном случае тип name инферится из типа строки. Это поле не обязательно, так как установлено дефолтное значение. Тогда создавая инстанс класса, мы получим аттрибуты:

```python
user = User(id='123')

assert user.id == 123
assert user.name == 'Jane Doe'

# name не создается при инициализации, т.к. имеет дефолтное значение
assert user.__fields_set__ == {'id'}

# поля полученные, при инициализации
assert user.dict() == dict(user) == {'id': 123, 'name': 'Jane Doe'}

# наконец, у нас есть полный доступ к атрибутам
user.id = 321
assert user.id == 321
```

[Свойства модели](https://pydantic-docs.helpmanual.io/usage/models/#model-properties):

- `dict()` словарь полей и значений модели
- `json()` тоже вамое в виде json
- `copy()` копия модели (по дефолту shallow)
- `parse_obj()` метод для парсинга и лоада объекта в модель с выдачей ошибки, если объект не похож на fict
- `parse_raw()` тоже самое из json
- `parse_file()` из файла
- `from_orm()` из класса ОРМ
- `schema()` возвращает json-схему в виде словаря
- `schema_json()` в виде json
- `construct()` создание модели без валидации (когда данные из проверенногно источника - на в 30 раз быстрее)
- `_fields_set__` имена полей в виде множества
- `__fields__` словарь полей
- `__config__` конфиг

#### Можно выстраивать модели иерархически

```python
from typing import List
from pydantic import BaseModel


class Foo(BaseModel):
    count: int
    size: float = None


class Bar(BaseModel):
    apple = 'x'
    banana = 'y'


class Spam(BaseModel):
    foo: Foo
    bars: List[Bar]

m = Spam(foo={'count': 4}, bars=[{'apple': 'x1'}, {'apple': 'x2'}])
print(m)
#> foo=Foo(count=4, size=None) bars=[Bar(apple='x1', banana='y'),
#> Bar(apple='x2', banana='y')]
print(m.dict())
"""
{
    'foo': {'count': 4, 'size': None},
    'bars': [
        {'apple': 'x1', 'banana': 'y'},
        {'apple': 'x2', 'banana': 'y'},
    ],
}
"""
```

#### ORM модели

```python
from typing import List
from sqlalchemy import Column, Integer, String
from sqlalchemy.dialects.postgresql import ARRAY
from sqlalchemy.ext.declarative import declarative_base
from pydantic import BaseModel, constr

Base = declarative_base()


class CompanyOrm(Base):
    __tablename__ = 'companies'
    id = Column(Integer, primary_key=True, nullable=False)
    public_key = Column(String(20), index=True, nullable=False, unique=True)
    name = Column(String(63), unique=True)
    domains = Column(ARRAY(String(255)))


class CompanyModel(BaseModel):
    id: int
    public_key: constr(max_length=20)
    name: constr(max_length=63)
    domains: List[constr(max_length=255)]

    class Config:
        orm_mode = True


co_orm = CompanyOrm(
    id=123,
    public_key='foobar',
    name='Testing',
    domains=['example.com', 'foobar.com'],
)
print(co_orm)
#> <models_orm_mode.CompanyOrm object at 0x7fb266c7ef40>
co_model = CompanyModel.from_orm(co_orm)
print(co_model)
#> id=123 public_key='foobar' name='Testing' domains=['example.com',
#> 'foobar.com']
```

Иногда нужно дать название колонке, после того, как зарезервирвоано название поля.

```python
import typing

from pydantic import BaseModel, Field
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base


class MyModel(BaseModel):
    metadata: typing.Dict[str, str] = Field(alias='metadata_')

    class Config:
        orm_mode = True


BaseModel = declarative_base()


class SQLModel(BaseModel):
    __tablename__ = 'my_table'
    id = sa.Column('id', sa.Integer, primary_key=True)
    # 'metadata' is reserved by SQLAlchemy, hence the '_'
    metadata_ = sa.Column('metadata', sa.JSON)


sql_model = SQLModel(metadata_={'key': 'val'}, id=1)

pydantic_model = MyModel.from_orm(sql_model)

print(pydantic_model.dict())
#> {'metadata': {'key': 'val'}}
print(pydantic_model.dict(by_alias=True))
#> {'metadata_': {'key': 'val'}}
```

ORM модели [могут быть рекурсивными](https://pydantic-docs.helpmanual.io/usage/models/#recursive-orm-models)

### Доступ к ошибкам

[Осуществляется через ValidationError](https://pydantic-docs.helpmanual.io/usage/models/#error-handling). Поднимается один эксепшен вне зависимости от кол-ва ошибок, с информацией по которому можно работать через несколько методов. Кроме того, можно реализовать кастомные ошибки.

### Поддерживаются дополнительные методы создания моделей (см. в models)

Например [можно сделать даныне модели неизменяемыми](https://pydantic-docs.helpmanual.io/usage/models/#faux-immutability). Можно создавать [дженерик модели](https://pydantic-docs.helpmanual.io/usage/models/#generic-models) для последующего использования в качестве "шаблона". Можно [использовать абстрактные базовы классы](https://pydantic-docs.helpmanual.io/usage/models/#abstract-base-classes), [устанавливать строгий порядок полей](https://pydantic-docs.helpmanual.io/usage/models/#field-ordering) (поля должны оставаться в том порядке, в котором они были заданы в модели)

### [Обязательные поля](https://pydantic-docs.helpmanual.io/usage/models/#required-fields)

```python
from pydantic import BaseModel, Field

class Model(BaseModel):
    a: int
    b: int = ...
    c: int = Field(...)
```

вариант рекуаред поля с опциональным значением

```python
class Model(BaseModel):
    a: Optional[int]
    b: Optional[int] = ...
    c: Optional[int] = Field(...)
```

### [Поля с динамическим required значением](https://pydantic-docs.helpmanual.io/usage/models/#field-with-dynamic-default-value)

С помощью `default_factory`

```python
from datetime import datetime
from uuid import UUID, uuid4
from pydantic import BaseModel, Field


class Model(BaseModel):
    uid: UUID = Field(default_factory=uuid4)
    updated: datetime = Field(default_factory=datetime.utcnow)
```

### Автоматическая конфертация

Пайдантик автоматически конвертирует некотоыре типы данных, что может привести к потере информации

```python
from pydantic import BaseModel


class Model(BaseModel):
    a: int
    b: float
    c: str

print(Model(a=3.1415, b=' 2.72 ', c=123).dict())
#> {'a': 3, 'b': 2.72, 'c': '123'}
```

## [Типы полей](https://pydantic-docs.helpmanual.io/usage/types/)

Поддерживает все стандартные типы #python

- [strict types](https://pydantic-docs.helpmanual.io/usage/types/#strict-types)
- [constrained types](https://pydantic-docs.helpmanual.io/usage/types/#constrained-types)

Типы:

- `None` or `type(None)` or `Literal[None]`
- `bool`
- `int`
- `float`
- `str`
- `bytes`
- `list` (принимает list, tuple, set, frozenset, deque и генераторы)
- `tuple` (принимает list, tuple, set, frozenset, deque и генераторы)
- `dict`
- `set` (принимает list, tuple, set, frozenset, deque и генераторы)
- `frozenset` (принимает list, tuple, set, frozenset, deque и генераторы)
- `deque` (принимает list, tuple, set, frozenset, deque и генераторы)
- `datetime.date`
- `datetime.time`
- `datetime.datetime`
- `datetime.timedelta`
- `typing.Any` любое значение
- `typing.Annotated` анотированное значение
- `typing.TypeVar` константа, базирующаяся на [этом](https://pydantic-docs.helpmanual.io/usage/types/#typevar)
- `typing.Union` [несколько разных типов](https://pydantic-docs.helpmanual.io/usage/types/)
- `typing.Optional` обертка над `Union[x, None]`
- `typing.List`
- `typing.Tuple`
- subclass of `typing.NamedTuple`
- subclass of `collections.namedtuple`
- `typing.Dict` и subclass
- `typing.Set`
- `typing.FrozenSet`
- `typing.Deque`
- `typing.Sequence`
- `typing.Iterable` зарезевировано под другие итераторы
- `typing.Type`
- `typing.Callable`
- `typing.Pattern` для regex
- `ipaddress.IPv4Address` и другие ip...
- `enum.Enum` и subclass of `enum.Enum`
- `enum.IntEnum` и subclass
- `decimal.Decimal` конвертит в строку, затем в decimal
- `pathlib.Path`
- `uuid.UUID`
- `ByteSize`

Пример с итераторами

```python
from typing import (
    Deque, Dict, FrozenSet, List, Optional, Sequence, Set, Tuple, Union
)

from pydantic import BaseModel


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

    simple_tuple: tuple = None
    tuple_of_different_types: Tuple[int, float, str, bool] = None

    simple_dict: dict = None
    dict_str_float: Dict[str, float] = None

    simple_set: set = None
    set_bytes: Set[bytes] = None
    frozen_set: FrozenSet[int] = None

    str_or_bytes: Union[str, bytes] = None
    none_or_str: Optional[str] = None

    sequence_of_ints: Sequence[int] = None

    compound: Dict[Union[str, bytes], List[Set[int]]] = None

    deque: Deque[int] = None
```

### DateTime типы

- datetime fields can be:
  - datetime, existing datetime object
  - int or float, assumed as Unix time, i.e. seconds (if >= -2e10 or <= 2e10) or milliseconds (if < -2e10or > 2e10) since 1 January 1970
  - str, following formats work:
    - YYYY-MM-DD[T]HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]]]
    - int or float as a string (assumed as Unix time)
- date fields can be:
  - date, existing date object
  - int or float, see datetime
  - str, following formats work:
    - YYYY-MM-DD
    - int or float, see datetime
- time fields can be:
  - time, existing time object
  - str, following formats work:
    - HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]]]
- timedelta fields can be:
  - timedelta, existing timedelta object
  - int or float, 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)

### Boolean

Будет ошибка валидации, если значение не одно из;

- True or False
- 0 or 1
- 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 to str

### [Calable](https://pydantic-docs.helpmanual.io/usage/types/#callable)

Позволяет передавать функцию и указывать, какой выход в ней ожидается. Валидация не проверяте типы аргументов функции, только то, что этот объект вызываемый.

### [Type](https://pydantic-docs.helpmanual.io/usage/types/#type)

Когда мы должны проверить, что объект является производным от  `tyoe`, т.е. классом, не инстансом.

### [Literal Type](https://pydantic-docs.helpmanual.io/usage/types/#literal-type)

Появился в #python 3.8 `typing.Literal` (или `typing_extensions.Literal` для 3.8). позволяет определить только специфичные значения литералов. Позволяет проверять одно или больше специфичных значений без использования валидаторов.

```python
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))
```

Пример с Union

```python
from typing import Optional, Union

from typing import Literal

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__)
#> Pie
print(type(Meal(dessert={'kind': 'cake'}).dessert).__name__)
#> Dessert
```

### [Анотированные типы](https://pydantic-docs.helpmanual.io/usage/types/#annotated-types)

Пример с NamedTuple

```python
from typing import NamedTuple

from pydantic import BaseModel, ValidationError


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


class Model(BaseModel):
    p: Point


print(Model(p=('1', '2')))
#> p=Point(x=1, y=2)
```

### [pydantic types](https://pydantic-docs.helpmanual.io/usage/types/#pydantic-types)

- `FilePath`
- `DirectoryPath`
- `EmailStr`
- `NameEmail`
- `PyObject`
- `Color` html/css цвет вот [в таком формате](https://pydantic-docs.helpmanual.io/usage/types/#color-type). Поддерживается несколько методов конвертации.
- `Json` [Пример](https://pydantic-docs.helpmanual.io/usage/types/#json-type)
- `PaymentCardNumber` [Пример](https://pydantic-docs.helpmanual.io/usage/types/#payment-card-numbers)
- `AnyUrl` [описание про урлы](https://pydantic-docs.helpmanual.io/usage/types/#urls)
- `AnyHttpUrl`
- `HttpUrl`
- `PostgresDsn`
- `RedisDsn`
- `stricturl`
- `UUID1` и 2, 3, 4, 5
- `SecretBytes` и т.д. [если нужно скрыт часть инфы из логирования](https://pydantic-docs.helpmanual.io/usage/types/#secret-types)
- `IPvAnyAddress` и т.д.
- `NegativeFloat` и т.д.
- несколько методов, которые принимают методы, содержащие другие типы

### [Constrained types](https://pydantic-docs.helpmanual.io/usage/types/#constrained-types)

Ограничение типов по форматам, диапазонам и т.д. через приставку con*

```python
from decimal import Decimal

from pydantic import (
    BaseModel,
    NegativeFloat,
    NegativeInt,
    PositiveFloat,
    PositiveInt,
    NonNegativeFloat,
    NonNegativeInt,
    NonPositiveFloat,
    NonPositiveInt,
    conbytes,
    condecimal,
    confloat,
    conint,
    conlist,
    conset,
    constr,
    Field,
)


class Model(BaseModel):
    lower_bytes: conbytes(to_lower=True)
    short_bytes: conbytes(min_length=2, max_length=10)
    strip_bytes: conbytes(strip_whitespace=True)

    lower_str: constr(to_lower=True)
    short_str: constr(min_length=2, max_length=10)
    regex_str: constr(regex=r'^apple (pie|tart|sandwich)$')
    strip_str: constr(strip_whitespace=True)

    big_int: conint(gt=1000, lt=1024)
    mod_int: conint(multiple_of=5)
    pos_int: PositiveInt
    neg_int: NegativeInt
    non_neg_int: NonNegativeInt
    non_pos_int: NonPositiveInt

    big_float: confloat(gt=1000, lt=1024)
    unit_interval: confloat(ge=0, le=1)
    mod_float: confloat(multiple_of=0.5)
    pos_float: PositiveFloat
    neg_float: NegativeFloat
    non_neg_float: NonNegativeFloat
    non_pos_float: NonPositiveFloat

    short_list: conlist(int, min_items=1, max_items=4)
    short_set: conset(int, min_items=1, max_items=4)

    decimal_positive: condecimal(gt=0)
    decimal_negative: condecimal(lt=0)
    decimal_max_digits_and_places: condecimal(max_digits=2, decimal_places=2)
    mod_decimal: condecimal(multiple_of=Decimal('0.25'))

    bigger_int: int = Field(..., gt=10000)
```

Описание всех аргументов (методов) [смотри там же](https://pydantic-docs.helpmanual.io/usage/types/#constrained-types)

Есть еще несколько специфичных случаев и можно задавать свои типы.

## Validators

[Использование классметода для валидации данных в модели](https://pydantic-docs.helpmanual.io/usage/validators/)

Это позволяет возвращать определенные данные, после валидации

```python
from pydantic import BaseModel, ValidationError, validator


class UserModel(BaseModel):
    name: str
    username: str
    password1: str
    password2: str

    @validator('name')
    def name_must_contain_space(cls, v):
        if ' ' not in v:
            raise ValueError('must contain a space')
        return v.title()

    @validator('password2')
    def passwords_match(cls, v, values, **kwargs):
        if 'password1' in values and v != values['password1']:
            raise ValueError('passwords do not match')
        return v

    @validator('username')
    def username_alphanumeric(cls, v):
        assert v.isalnum(), 'must be alphanumeric'
        return v


user = UserModel(
    name='samuel colvin',
    username='scolvin',
    password1='zxcvbn',
    password2='zxcvbn',
)
print(user)
#> name='Samuel Colvin' username='scolvin' password1='zxcvbn' password2='zxcvbn'

try:
    UserModel(
        name='samuel',
        username='scolvin',
        password1='zxcvbn',
        password2='zxcvbn2',
    )
except ValidationError as e:
    print(e)
    """
    2 validation errors for UserModel
    name
      must contain a space (type=value_error)
    password2
      passwords do not match (type=value_error)
    """
```

В разделе примеры как использовать кастом валидацию.

## [Config](https://pydantic-docs.helpmanual.io/usage/model_config/)

```python
class Sprints(BaseModel):
    user: User
    sprints: List[Sprint]

    class Config:
        orm_mode = True
```

- `title` заголовко json схемы
- `anystr_strip_whitespace` и т.д.
- `validate_all`
- `extra` забыть, применить или игнорировать экстра атрибуты при инциализации
- `allow_mutation` для неизменяемых типов
- `frozen` открывает дорогу к хешированию инстансов модели
- ...
- `orm_mode` использовать как модель для ORM
- `alias_generator`
- `schema_extra`
- `json_loads` кастомные ф-ии для json
- `json_dumps`
- `json_encoders`

Сконфигурировать можно глобально, вот так:

```python
class BaseModel(PydanticBaseModel):
    class Config:
        arbitrary_types_allowed = True
```

## [Alias](https://pydantic-docs.helpmanual.io/usage/model_config/#alias-precedence)

Пример алиас-генератора, чтобы перегнать все змеиные имена в верблюжьи

```python
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'}
```

## [SCHEMA](https://pydantic-docs.helpmanual.io/usage/schema/)

Возвращается json-схема, в т.ч. можно в [[openapi-specification]]

[Смотри статью](https://pydantic-docs.helpmanual.io/usage/schema/) про данные, которые попадают в схему, анотированные типы в схеме, валидацию схемы и кастомизацию:

## [Экспорт моделей](https://pydantic-docs.helpmanual.io/usage/exporting_models/) в другие форматы данных

## [Dataclasses](https://pydantic-docs.helpmanual.io/usage/dataclasses/)

## Использование [validate_arguments](https://pydantic-docs.helpmanual.io/usage/validation_decorator/)

Находится в бете с версии 1.5. Пример использования:

```python
from pydantic import validate_arguments, ValidationError


@validate_arguments
def repeat(s: str, count: int, *, separator: bytes = b'') -> bytes:
    b = s.encode()
    return separator.join(b for _ in range(count))


a = repeat('hello', 3)
print(a)
#> b'hellohellohello'

b = repeat('x', '4', separator=' ')
print(b)
#> b'x x x x'

try:
    c = repeat('hello', 'wrong')
except ValidationError as exc:
    print(exc)
    """
    1 validation error for Repeat
    count
      value is not a valid integer (type=type_error.integer)
    """
```

Аргументы для валидации инфирятся из аннотации типов функции. Если тип не анотирован, он инферится как `any`

## [Settings managements](https://pydantic-docs.helpmanual.io/usage/settings/)

Если создать модель и унаследовать ее от `BaseSettings`, эта модель позволит определить значения любых полей, которые не определены ключевым аргументом, из переменных окружения. Это позволяет сделать следующее:

- сделать понятный класс конфигураций для приложения
- автоматически чиать конфигурации из переменных окружения
- в ручную переписывать специфические настройки, к примеру для тестов

```python
from typing import Set

from pydantic import (
    BaseModel,
    BaseSettings,
    PyObject,
    RedisDsn,
    PostgresDsn,
    Field,
)


class SubModel(BaseModel):
    foo = 'bar'
    apple = 1


class Settings(BaseSettings):
    auth_key: str
    api_key: str = Field(..., env='my_api_key')

    redis_dsn: RedisDsn = 'redis://user:pass@localhost:6379/1'
    pg_dsn: PostgresDsn = 'postgres://user:pass@localhost:5432/foobar'

    special_function: PyObject = 'math.cos'

    # to override domains:
    # export my_prefix_domains='["foo.com", "bar.com"]'
    domains: Set[str] = set()

    # to override more_settings:
    # export my_prefix_more_settings='{"foo": "x", "apple": 1}'
    more_settings: SubModel = SubModel()

    class Config:
        env_prefix = 'my_prefix_'  # defaults to no prefix, i.e. ""
        fields = {
            'auth_key': {
                'env': 'my_auth_key',
            },
            'redis_dsn': {
                'env': ['service_redis_dsn', 'redis_url']
            }
        }


print(Settings().dict())
"""
{
    'auth_key': 'xxx',
    'api_key': 'xxx',
    'redis_dsn': RedisDsn('redis://user:pass@localhost:6379/1',
scheme='redis', user='user', password='pass', host='localhost',
host_type='int_domain', port='6379', path='/1'),
    'pg_dsn': PostgresDsn('postgres://user:pass@localhost:5432/foobar',
scheme='postgres', user='user', password='pass', host='localhost',
host_type='int_domain', port='5432', path='/foobar'),
    'special_function': <built-in function cos>,
    'domains': set(),
    'more_settings': {'foo': 'bar', 'apple': 1},
}
"""
```

Есть [.env поддержка](https://pydantic-docs.helpmanual.io/usage/settings/#dotenv-env-support)

.env файл

```yaml
# ignore comment
ENVIRONMENT="production"
REDIS_ADDRESS=localhost:6379
MEANING_OF_LIFE=42
MY_VAR='Hello world'
```

создание модели настроек

```python
class Settings(BaseSettings):
    ...

    class Config:
        env_file = '.env'
        env_file_encoding = 'utf-8'
```

Создание инстанса настроек

```python
settings = Settings(_env_file='prod.env', _env_file_encoding='utf-8')
```

## [Postponed annotations](https://pydantic-docs.helpmanual.io/usage/postponed_annotations/)

## [Использование devtools](https://pydantic-docs.helpmanual.io/usage/devtools/)

Смотри еще:

- [attrs](https://www.attrs.org/en/stable/) is the Python package that will bring back the joy of writing classes by relieving you from the drudgery of implementing object protocols (aka dunder methods)
- [[pydantic-factories]] This library offers powerful mock data generation capabilities for pydantic based models and dataclasses. It can also be used with other libraries that use pydantic as a foundation, for example SQLModel and Beanie.
- [[sql-model]]. SQLModel is a library for interacting with SQL databases from Python code, with Python objects. Используется в [[databases]] и [[fastapi]]
- [[pydantic-validation-custom]]
  [Pydantic Settings management](https://pydantic-docs.helpmanual.io/usage/settings/)
  [pydantic-computed](https://pypi.org/project/pydantic-computed/) а new decorator for pydantic allowing you to define dynamic fields that are computed from other properties.
- [[mock-libraries]]
- [[2023-01-23-daily-note]] закрытые атрибуты, женерики, корневые типы, корневые валидаторы, заполнение полей и ошибки в mypy
- **[awesome-pydantic](https://github.com/Kludex/awesome-pydantic)** A curated list of awesome things related to Pydantic!
- [[devtools]]
- [[fastapi-setting-environment-variables]] про поддержку .env
- [[fastapi]]
- [How to parse ObjectId in a pydantic model?](https://stackoverflow.com/questions/59503461/how-to-parse-objectid-in-a-pydantic-model)
- [Using bson.ObjectId in Pydantic v2](https://stackoverflow.com/questions/76686888/using-bson-objectid-in-pydantic-v2)
- [Remove an inherited field from a model in pydantic v2](https://github.com/pydantic/pydantic/discussions/6699), [Remove inherited/parent field from model](https://github.com/pydantic/pydantic/discussions/2686)


[type-annotation]: type-annotation "Аннотация типов в python"
[mypy]: mypy "Mypy"
[openapi-specification]: openapi-specification "Open-api v3 спецификация"
[pydantic-factories]: pydantic-factories "Pydantic-factories"
[sql-model]: sql-model "Sql model bd"
[databases]: databases "Databases python"
[fastapi]: fastapi "Fastapi"
[pydantic-validation-custom]: pydantic-validation-custom "Pydantic-validation-custom"
[mock-libraries]: mock-libraries "Либы для создания моков"
[2023-01-23-daily-note]: ../posts/2023-01-23-daily-note "Some pydantic tricks-1. Закрытые атрибуты, женерики, корневые типы, корневые валидаторы, заполнение полей и ошибки в mypy"
[devtools]: devtools "Python devtools"
[fastapi-setting-environment-variables]: fastapi-setting-environment-variables "Fastapi environment variables"