В этой статье мы поделимся несколькими идеями и лайфхаками, которые облегчат вам работу с библиотекой Django REST Framework. Она работает со стандартными моделями Django и дает возможность создавать гибкие и мощные API. Все примеры, которые мы покажем в данной статье, совместимы с версией 3 DRF.
Логотип DRF 3
1. Viewsets (представления)
Начнем с простой функциональности Django REST Framework. Viewsets можно рассматривать как очень полезный шаблон для построения API, который обеспечивает типичные взаимодействия с моделями Django. В то время как обычные представления (views) действуют как обработчики для HTTP методов, viewsets дают вам возможность определить действия, такие как create – создание экземпляра или list– список экземпляров (со стандартной разбивкой по страницам).
Самое замечательное в viewsets – это то, как они делают ваш код последовательным и спасают от повторения. Каждый раз, когда вы пишете представления, которые выполняют более одной функции, viewsets позволит сделать это быстрее.
Давайте представим, что в вашем проекте есть модель тегов, и вам нужно подготовить функционал, который позволит вашим пользователям:
a. перечислить все теги;
b. создать новый тег;
c. получить подробную информацию о теге.
Вот так вы сможете определить viewset для вышеперечисленного:
Viewset mixins могут быть комбинированы по мере необходимости. Вы можете определить свои собственные mixins или использовать ModelViewSet, который позволяет выполнить следующие команды: .list(), .retrieve(), .create(), .update(), .partial_update() and .destroy().
Кроме того, при использовании viewsets обычно задействуются маршрутизаторы (routers) для конфигурации url. Составление именований url станет для вас хорошей практикой, что позволит сделать ваши URL-адреса API более предсказуемыми.
Теперь ваш viewset достаточно функционален, чтобы вы могли:
· составить список всех тегов, отправив GET запрос на v1/tag/;
· создать новый тег с помощью POST запроса на v1/tag/;
· или извлечь один из тегов используя GET v1/tag/<tag_id>.
Вы даже можете добавить произвольные действия квашему viewset, используя декоратор @action.
Теперь написание представлений завершено, и вы сохранили достаточно времени для чашечки кофе.
2. Понимание разных видов сериализаторов
Как DRF пользователю вам уже больше не нужно утруждать себя написанием представлений и url конфигурациями, потому что теперь у вас появится достаточно времени для сериализаторов, которые работают как трансляторы между примерами моделей Django и их репрезентациями (например, json). Существует несколько функций, связанных с сериализаторами, о которых вам стоит узнать.
Каждый сериализатор можно использовать как для чтения, так и для записи. То, как инициализируется сериализатор, определяет действие, которое он будет выполнять. Таким образом можно выделить 3 типа операций: создание экземпляра (create), обновление экземпляра (update), получение / чтение экземпляра (retrieve).
Если в представлении (view) вам нужно сериализировать данные, которые будет возвращать API, попробуйте следовать приведенным ниже действиям:
Но в представлении предназначенном для создания нового экземпляравам придется сделать это немного по-другому:
И наконец, во время обновления экземпляравам нужно передать параметр instance также, как data:
3. Использование SerializerMethodField
SerializerMethodField – поле для чтения, которое вычисляет свое значение во время обработки, вызывая метод сериализатора, к которому он присоединен. Предположим, что у вас есть модель, которая хранит данные о дате и времени в models.DateTimeField, но вы хотите использовать UNIX-формат в репрезентации сериализатора:
SerializerMethodField принимает method_name, но обычно для именования этих методов намного удобнее использовать шаблон, который по умолчанию называется get_<field_name>. Просто убедитесь, что вы не перегружаете эти методы какими-либо тяжелыми операциями.
4. Использование параметра source
Довольно часто наименования полей в модели отличаются от требуемых в репрезентации. Использование параметра source позволит вам с легкостью с этим справится. Взглянем на пример:
Поле task_type находится в модели Task, но в вашем API это будет названо, как job_type. Это работает как для чтения, так и для написания операций.
Более того, вы можете использовать его для извлечения данных из связанных объектов при помощи точечной нотации:
5. Валидация поля сериализатора
Помимо аргумента validators, который можно передавать во время инициализации полей и хука serializer.validate(), также существует валидация на уровне полей, которая позволяет определить уникальный валидатор для каждого отдельного поля.
Есть две причины, по которым мы находим этот тип валидаторов полезным:
· он разделяет разные проверки, связанные только с определенным полем;
· он генерирует хорошо отформатированные ответы на ошибки.
Использование такого рода проверки аналогично использованию SerializerMethodField, но в этот раз применяется другая конвенция наименований: def validate_<field_name>.
Вот пример:
Если bid превысит баланс пользователя, ответ на такой запрос будет выглядеть следующим образом:
Методы валидации всегда должны возвращать значение, которое позднее передается экземпляру метода. Учтите, что валидация полей вызывается в методе serializer.to_internal_value(), который используется перед командой serializer.validate().
О других лайфхаках мы расскажем в следующей публикации. Спасибо за ваши лайки и комментарии!
Перевод статьи Łukasz German.