Python pydantic. Валидация данных

05 Апр 2021 , 1305

Изучая FastAPI  я познакомился с замечательной библиотекой Pydantic. В документации FastAPI  отмечается, что "FastAPI стоит на плечах гигантов Starlette(асинхронный веб-фреймворк , который занимается работой с web) и Pydantic(который служит для валидации данных). 


В статье "Введение FastAPI" я на реальном примере описал использование Pydantic в связке с SQLAlchemy. А в данной статье мне хочется разобраться с самой библиотекой Pydantic, который используется во многих проектах по всему миру

Что такое Pydantic?

Pydantic - это библиотека , которая обеспечивает проверку данных и управление настройками с использованием аннотаций типов(type annotations)

Установим pydantic


pip install pydantic

Модели

Основным средством определения объектов в pydantic являются модели (модели — это просто классы, которые наследуются от BaseModel).

Создадим первую pydantic модель для поста(Post). Для этого нам нужно будет отнаследоваться от BaseModel. Передадим этой модели сырые данные и посмотрим , что получится. Ниже в примерах код будет работать на Python версии 3.10 и выше.


from datetime import datetime
from pydantic import BaseModel


class Post(BaseModel):
    id: int
    title: str
    text: str
    is_published: bool
    tags: list[str] = []
    published_at: datetime | None = None


if __name__ == '__main__':
    input_data = {
        'id': '1',
        'title': 'Python decorators',
        'text': 'Python decorators text',
        'is_published': True,
        'published_at': '2019-06-01 12:22',
        'tags': ['python', 'js', 3],
        'another_field': 'Test data',
    }
    post = Post(**input_data)
    print(post.id, type(post.id))
    #> 1 
    print(post.published_at, repr(post.published_at))
    #> 2019-06-01 12:22:00 datetime.datetime(2019, 6, 1, 12, 22)
    print("Выводим словарь", post.dict())
    #> Выводим словарь {'id': 1, 'title': 'Pyton decorators', 'text': 'Python decorators text',
    # 'is_published': True, 'tags': ['python', 'js', '3'], 'published_at': datetime.datetime(2019, 6, 1, 12, 22)}
    print("Выводим данные в json", post.json())
    #> Выводим данные в json {"id": 1, "title": "Python decorators", "text": "Python decorators text",
    # "is_published": true, "tags": ["python", "js", "3"], "published_at": "2019-06-01T12:22:00"}


Разберем , что происходит при запуске данного скрипта

- id - имеет целочисленный тип(int) и это поле является обязательным. Как видно выше значение в id мы передали строковое значение , но pydantic его преобразовал его целочисленный. Строки(str), байты(bytes) и числа плавающей запятой pydantic по возможности преобразует в целочисленный. В противном случае возбуждается исключение. Покажем это на примере ниже


from pydantic import BaseModel


class Example(BaseModel):
    id: int

if __name__ == '__main__':
    print(Example(id='1')) # строковое значние будет преобразовано в 1
    #> id=1
    print(Example(id=1.123)) # float преобразуется в 1 (отсекается дробовая часть)
    #> id=1

    # Возникнет исключение валидации ,потому что строковое значние невозможно преобразовать в целочисленный
    print(Example(id='this is str'))
    #> pydantic.error_wrappers.ValidationError: 1 validation error for Example
    # id
    # value is not a valid integer (type=type_error.integer)

name - поле имеет строковый тип и является обязательным.

text - поле имеет строковый тип и является обязательным.

is_published - поле имеет булев тип и по умолчанию имеет значение True(Истинно)

published_at - это поле даты и времени, которое не требуется (и принимает значение None, если оно не указано). pydantic будет обрабатывать либо временную метку unix int (например, 1496498400), либо строку, представляющую дату и время.

tags - требует список строковых значений. По возможности входящие значения pydantic будет преобразоывать в строковые значения

Мы создаем объект модели Post и передаем данные. Так как данные валидные , то создается новый объект и при этом как указали выше , некоторые входные данные преобразуются в тот тип , который указан в аннотациях полей.Как видим выше во входных данных(input_data) у нас есть поле another_field, но такого поля нет в модели и поэтому значение этого поля игнорируется

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


from pydantic import ValidationError

try:
    post = Post(**input_data)
except ValidationError as e:
    print(e.json())


Далее мы используем два метода , которые выводят данные в виде словаря(метод BaseModel.dict()) и виде json (метод BaseModel.json()). Есть еще другие методы и атрибуты модели , которые мы рассмотрим ниже

Методы модели BaseModel

dict() - Возвращает словарь поля и значения модели

json() - Возвращает строковое представление JSON метода dict()

copy() - Возвращает копию модели(по умолчанию поверхностное копирование)

parse_obj()- метод для загрузки любого объекта в модель с обработкой ошибок, если объект не является словарем

parse_raw() - метод для загрузки строк различных форматов

parse_file() - похож на parse_raw() но для путей к файлам;

from_orm() - загружает данные в модель из произвольного класса; (режим ORM)

schema() - возвращает словарь, представляющий модель в виде схемы JSON.

schema_json() - Возвращает строковое представление JSON метода schema()

construct() - метод класса для создания моделей без запуска проверки

Заключение

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

comments powered by Disqus

Подписка

Подпишитесь на наш список рассылки, чтобы получать обновления из блога

Рубрики

Теги