Как сериализатор работает в django rest framework

Обновлено: 21.11.2024

В этом руководстве рассказывается о создании простого кода pastebin с выделением Web API. Попутно он познакомит вас с различными компонентами, составляющими среду REST, и даст вам полное представление о том, как все сочетается друг с другом.

Учебное пособие довольно подробное, поэтому перед началом работы вам, вероятно, следует выпить печенье и чашку любимого напитка. Если вам нужен только краткий обзор, вам следует перейти к документации по быстрому запуску.

Примечание. Код для этого руководства доступен в репозитории tomchristie/rest-framework-tutorial на GitHub. Завершенная реализация также находится в Интернете в виде тестовой версии для тестирования, доступной здесь.

Настройка новой среды

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

Теперь, когда мы находимся в среде virtualenv, мы можем установить наши требования к пакету.

Примечание. Чтобы в любой момент выйти из среды virtualenv, просто введите deactivate . Дополнительные сведения см. в документации по virtualenv.

Начало работы

Хорошо, мы готовы приступить к программированию. Для начала давайте создадим новый проект для работы.

После этого мы можем создать приложение, которое будем использовать для создания простого веб-API.

Самый простой способ приступить к работе — использовать базу данных sqlite3 для обучения. Отредактируйте файл tutorial/settings.py и задайте для базы данных по умолчанию «ENGINE» значение «sqlite3» , а «NAME» — «tmp.db» .

Нам также потребуется добавить наше новое приложение фрагментов кода и приложение rest_framework в INSTALLED_APPS.

Нам также нужно связать корневую urlconf в файле tutorial/urls.py, чтобы включить URL-адреса нашего приложения-фрагмента.

Хорошо, мы готовы к работе.

Создание модели для работы

Для целей этого руководства мы начнем с создания простой модели Snippet, которая используется для хранения фрагментов кода. Идите вперед и отредактируйте файл models.py приложения фрагментов. Примечание. Надлежащая практика программирования включает комментарии. Хотя вы найдете их в нашей версии репозитория этого учебного кода, мы опустили их здесь, чтобы сосредоточиться на самом коде.

Не забудьте синхронизировать базу данных в первый раз.

Создание класса Serializer

Первое, что нам нужно для начала работы с нашим веб-API, – предоставить способ сериализации и десериализации экземпляров фрагментов в представления, такие как json . Мы можем сделать это, объявив сериализаторы, которые работают очень похоже на формы Django. Создайте файл в каталоге snippets с именем serializers.py и добавьте следующее.

Первая часть класса сериализатора определяет поля, которые будут сериализованы/десериализованы. Метод restore_object определяет, как создаются полноценные экземпляры при десериализации данных.

Обратите внимание, что мы также можем использовать различные атрибуты, которые обычно используются в полях формы, например, widget=widgets.Textarea . Их можно использовать для управления тем, как должен отображаться сериализатор при отображении в виде HTML-формы. Это особенно полезно для управления тем, как должен отображаться доступный для просмотра API, как мы увидим позже в этом руководстве.

На самом деле мы также можем сэкономить время, используя класс ModelSerializer, как мы увидим позже, но пока мы оставим определение нашего сериализатора явным.

Работа с сериализаторами

Прежде чем двигаться дальше, мы ознакомимся с использованием нашего нового класса Serializer. Перейдем к оболочке Django.

Хорошо, когда мы закончим с импортом, давайте создадим пару фрагментов кода для работы.

Теперь у нас есть несколько экземпляров фрагмента для экспериментов. Давайте посмотрим на сериализацию одного из этих экземпляров.

На данный момент мы перевели экземпляр модели в собственные типы данных Python. Чтобы завершить процесс сериализации, мы визуализируем данные в формате json.

Десериализация аналогична. Сначала мы разбираем поток на родные типы данных Python.

<р>. затем мы восстанавливаем эти собственные типы данных в полностью заполненный экземпляр объекта.

Обратите внимание, насколько API похож на работу с формами. Сходство должно стать еще более очевидным, когда мы начнем писать представления, использующие наш сериализатор.

Мы также можем сериализовать наборы запросов вместо экземпляров модели. Для этого мы просто добавляем флаг many=True к аргументам сериализатора.

Использование сериализаторов моделей

Наш класс SnippetSerializer копирует большое количество информации, которая также содержится в модели Snippet. Было бы неплохо, если бы мы могли сделать наш код более лаконичным.

Точно так же, как Django предоставляет как классы Form, так и классы ModelForm, платформа REST включает в себя как классы Serializer, так и классы ModelSerializer.

Давайте рассмотрим рефакторинг нашего сериализатора с помощью класса ModelSerializer.Снова откройте файл snippets/serializers.py и отредактируйте класс SnippetSerializer.

Написание обычных представлений Django с помощью нашего сериализатора

Давайте посмотрим, как мы можем написать некоторые представления API, используя наш новый класс Serializer. На данный момент мы не будем использовать какие-либо другие функции среды REST, мы просто напишем представления как обычные представления Django.

Отредактируйте файл snippets/views.py и добавьте следующее.

Корнем нашего API будет представление, поддерживающее вывод списка всех существующих фрагментов или создание нового фрагмента.

Обратите внимание: поскольку мы хотим, чтобы клиенты, у которых не будет маркера CSRF, могли отправлять POST в это представление, нам нужно пометить представление как csrf_exempt . Это не то, что вы обычно хотели бы делать, и представления инфраструктуры REST на самом деле используют более разумное поведение, чем это, но прямо сейчас это подойдет для наших целей.

Нам также потребуется представление, которое соответствует отдельному фрагменту и может использоваться для извлечения, обновления или удаления фрагмента.

Наконец нам нужно связать эти представления. Создайте файл snippets/urls.py:

Стоит отметить, что есть несколько пограничных случаев, с которыми мы пока не работаем должным образом. Если мы отправим искаженный json или если запрос будет сделан с помощью метода, который не обрабатывается представлением, мы получим ответ 500 «ошибка сервера». Тем не менее, пока этого достаточно.

Тестирование нашей первой попытки веб-API

Теперь мы можем запустить тестовый сервер, обслуживающий наши фрагменты кода.

Выйти из оболочки.

<р>. и запустите сервер разработки Django.

В другом окне терминала мы можем протестировать сервер.

Мы можем получить список всех фрагментов.

Или мы можем получить конкретный фрагмент, указав его идентификатор.

Точно так же вы можете отобразить тот же JSON, посетив эти URL-адреса в веб-браузере.

Где мы сейчас

Пока у нас все хорошо, у нас есть API сериализации, который очень похож на API форм Django, и некоторые обычные представления Django.

В настоящее время наши представления API не делают ничего особенного, кроме обслуживания ответов json, и есть некоторые пограничные случаи обработки ошибок, которые мы все еще хотели бы исправить, но это работающий веб-API.

Расширение полезности сериализаторов — это то, к чему мы хотели бы обратиться. Однако это не тривиальная проблема, и она потребует серьезной работы над проектом.

— Рассел Кит-Маги, группа пользователей Django

Сериализаторы позволяют преобразовывать сложные данные, такие как наборы запросов и экземпляры моделей, в собственные типы данных Python, которые затем можно легко преобразовать в JSON , XML или другие типы контента. Сериализаторы также обеспечивают десериализацию, позволяя преобразовывать проанализированные данные обратно в сложные типы после предварительной проверки входящих данных.

Сериализаторы REST framework работают очень похоже на классы Django Form и ModelForm. Он предоставляет класс Serializer, который дает вам мощный универсальный способ управления выводом ваших ответов, а также класс ModelSerializer, который предоставляет полезный ярлык для создания сериализаторов, которые работают с экземплярами модели и наборами запросов.

Объявление сериализаторов

Давайте начнем с создания простого объекта, который мы можем использовать в качестве примера:

Мы объявим сериализатор, который можно использовать для сериализации и десериализации объектов комментариев.

Объявление сериализатора очень похоже на объявление формы:

Первая часть класса сериализатора определяет поля, которые сериализуются/десериализуются. Метод restore_object определяет, как создаются полноценные экземпляры при десериализации данных.

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

Сериализация объектов

Теперь мы можем использовать CommentSerializer для сериализации комментария или списка комментариев. Опять же, использование класса Serializer очень похоже на использование класса Form.

На данный момент мы перевели экземпляр модели в собственные типы данных Python. Чтобы завершить процесс сериализации, мы визуализируем данные в формате json.

Настройка представления поля

Иногда при сериализации объектов вы можете не захотеть представлять все точно так, как оно есть в вашей модели.

Если вам нужно настроить сериализованное значение определенного поля, вы можете сделать это, создав метод transform_. Например, если вам нужно отобразить уценку из текстового поля:

Эти методы по существу обратны методу validate_ (см. раздел Проверка ниже).

Десериализация объектов

Десериализация аналогична. Сначала мы разбираем поток на родные типы данных Python.

<р>. затем мы восстанавливаем эти собственные типы данных в полностью заполненный экземпляр объекта.

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

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

Проверка

При десериализации данных вам всегда нужно вызывать is_valid(), прежде чем пытаться получить доступ к десериализованному объекту. Если возникают какие-либо ошибки проверки, свойство .errors будет содержать словарь, представляющий полученные сообщения об ошибках. Например:

Каждый ключ в словаре будет именем поля, а значениями будут списки строк любых сообщений об ошибках, соответствующих этому полю. Также может присутствовать ключ non_field_errors, в котором будут перечислены все общие ошибки проверки.

При десериализации списка элементов ошибки будут возвращены в виде списка словарей, представляющих каждый из десериализованных элементов.

Проверка на уровне поля

Вы можете указать пользовательскую проверку на уровне поля, добавив методы .validate_ в свой подкласс Serializer. Они аналогичны методам .clean_ в формах Django, но принимают немного другие аргументы.

Они принимают словарь десериализованных атрибутов в качестве первого аргумента и имя поля в этом словаре в качестве второго аргумента (которым будет либо имя поля, либо значение исходного аргумента для поля, если он был предоставлено).

Ваши методы validate_ должны либо просто возвращать словарь attrs, либо вызывать ValidationError . Например:

Проверка на уровне объекта

Чтобы выполнить любую другую проверку, требующую доступа к нескольким полям, добавьте метод с именем .validate() в свой подкласс Serializer. Этот метод принимает единственный аргумент, которым является словарь attrs. При необходимости он должен вызвать ValidationError или просто вернуть attrs. Например:

Сохранение состояния объекта

Чтобы сохранить десериализованные объекты, созданные сериализатором, вызовите метод .save():

По умолчанию этот метод просто вызывает .save() для десериализованного экземпляра объекта. Вы можете переопределить поведение сохранения по умолчанию, переопределив метод .save_object(obj) в классе сериализатора.

Общие представления, предоставляемые инфраструктурой REST, вызывают метод .save() при обновлении или создании объектов.

Работа с вложенными объектами

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

Класс Serializer сам по себе является типом Field и может использоваться для представления отношений, в которых один тип объекта вложен в другой.

Если вложенное представление может дополнительно принимать значение None, вы должны передать флаг required=False вложенному сериализатору.

Аналогично, если вложенное представление должно быть списком элементов, вы должны передать флаг many=True во вложенное сериализованное представление.

Проверка вложенных объектов будет работать так же, как и раньше. Ошибки с вложенными объектами будут вложены под именем поля вложенного объекта.

Работа с несколькими объектами

Класс Serializer также может выполнять сериализацию или десериализацию списков объектов.

Сериализация нескольких объектов

Чтобы сериализовать набор запросов или список объектов вместо одного экземпляра объекта, необходимо передать флаг many=True при создании экземпляра сериализатора. Затем вы можете передать набор запросов или список сериализуемых объектов.

Десериализация нескольких объектов для создания

Чтобы десериализовать список данных объекта и создать несколько экземпляров объекта за один проход, необходимо также установить флаг many=True и передать список данных для десериализации.

Это позволяет создавать представления, которые создают несколько элементов при выполнении запроса POST.

Десериализация нескольких объектов для обновления

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

Это позволяет вам создавать представления, которые обновляют или создают несколько элементов при выполнении запроса PUT.

По умолчанию массовые обновления будут ограничены обновлением экземпляров, которые уже существуют в предоставленном наборе запросов.

При выполнении массового обновления может потребоваться разрешить создание новых элементов и удаление отсутствующих элементов. Для этого передайте сериализатору allow_add_remove=True.

Передача параметра allow_add_remove=True гарантирует, что любые операции обновления будут полностью перезаписывать существующий набор запросов, а не просто обновлять существующие объекты.

Как определяется личность при массовых обновлениях

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

По умолчанию класс сериализатора будет использовать ключ id для входящих данных, чтобы определить каноническую идентичность объекта. Если вам нужно изменить это поведение, вы должны переопределить метод get_identity в классе Serializer. Например:

Чтобы сопоставить входящие элементы данных с соответствующими экземплярами объектов, метод .get_identity() будет вызываться как для входящих данных, так и для сериализованного представления существующих объектов.

Включение дополнительного контекста

В некоторых случаях вам необходимо предоставить сериализатору дополнительный контекст в дополнение к сериализуемому объекту. Одним из распространенных случаев является использование сериализатора, включающего гиперссылки, который требует, чтобы сериализатор имел доступ к текущему запросу, чтобы он мог правильно генерировать полные URL-адреса.

Вы можете предоставить произвольный дополнительный контекст, передав аргумент контекста при создании экземпляра сериализатора. Например:

Словарь контекста можно использовать в любой логике поля сериализатора, например в пользовательском методе .to_native(), путем обращения к атрибуту self.context.

Часто вам понадобятся классы сериализатора, которые точно сопоставляются с определениями модели. Класс ModelSerializer позволяет автоматически создать класс Serializer с полями, соответствующими полям модели.

По умолчанию все поля модели в классе будут сопоставлены с соответствующими полями сериализатора.

Любые отношения, такие как внешние ключи в модели, будут сопоставлены с PrimaryKeyRelatedField . Поля других моделей будут сопоставлены с соответствующим полем сериализатора.

Примечание. Когда проверка применяется к ModelSerializer , как поля сериализатора, так и соответствующие им поля модели должны пройти правильную проверку. Если у вас есть необязательные поля в модели, убедитесь, что в поле модели правильно задано значение empty=True, а в поле сериализатора — required=False.

Указание полей, которые должны быть включены

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

Указание вложенной сериализации

ModelSerializer по умолчанию использует первичные ключи для отношений, но вы также можете легко создавать вложенные представления, используя параметр глубины:

Для параметра depth должно быть задано целочисленное значение, указывающее глубину взаимосвязей, которые необходимо пройти, прежде чем вернуться к плоскому представлению.

Если вы хотите настроить способ сериализации (например, с помощью allow_add_remove ), вам нужно будет определить это поле самостоятельно.

Указание полей, которые должны быть доступны только для чтения

Возможно, вы захотите указать несколько полей только для чтения. Вместо явного добавления каждого поля с помощью атрибута read_only=True вы можете использовать мета-параметр read_only_fields, например:

Поля модели, для которых установлено значение editable=False, и поля AutoField по умолчанию будут доступны только для чтения, и их не нужно добавлять в параметр read_only_fields.

Указание полей, которые должны быть доступны только для записи

Возможно, вы захотите указать несколько полей только для записи. Вместо явного добавления каждого поля с помощью атрибута write_only=True вы можете использовать мета-параметр write_only_fields, например:

Явное указание полей

Вы можете добавить дополнительные поля в ModelSerializer или переопределить поля по умолчанию, объявив поля в классе точно так же, как в классе Serializer.

Дополнительные поля могут соответствовать любому свойству или вызываться в модели.

Реляционные поля

При сериализации экземпляров модели существует несколько различных способов представления отношений. Представление по умолчанию для ModelSerializer — использовать первичные ключи связанных экземпляров.

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

Подробнее см. в документации по отношениям сериализатора.

Класс HyperlinkedModelSerializer подобен классу ModelSerializer, за исключением того, что он использует гиперссылки для представления отношений, а не первичные ключи.

По умолчанию сериализатор будет включать поле URL вместо поля первичного ключа.

Поле URL будет представлено с помощью поля сериализатора HyperlinkedIdentityField, а любые отношения в модели будут представлены с помощью поля сериализатора HyperlinkedRelatedField.

Вы можете явно указать первичный ключ, добавив его в параметр fields, например:

Как определяются просмотры с гиперссылками

Должен быть способ определить, какие представления следует использовать для гиперссылок на экземпляры модели.

По умолчанию ожидается, что гиперссылки будут соответствовать имени представления, которое соответствует стилю '-detail', и ищет экземпляр с помощью аргумента ключевого слова pk.

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

Обратите внимание, что поле lookup_field будет использоваться по умолчанию для всех полей с гиперссылками, включая идентификатор URL и любые связи с гиперссылками.

Для более специфических требований, таких как указание разных поисковых запросов для каждого поля, вам потребуется явно указать поля в сериализаторе. Например:

Переопределение поведения поля URL

Название поля URL-адреса по умолчанию — "url". Вы можете переопределить это глобально, используя параметр URL_FIELD_NAME.

Вы также можете переопределить это для каждого сериализатора, используя параметр url_field_name в сериализаторе, например:

Примечание. Реализации универсального представления обычно генерируют заголовок Location в ответ на успешные запросы POST. Сериализаторы, использующие параметр url_field_name, не будут автоматически включать этот заголовок в представление. Если вам нужно это сделать, вам также потребуется переопределить метод представления get_success_headers().

Вы также можете переопределить имя представления и поле поиска в поле URL, не переопределяя поле явно, с помощью параметров view_name и lookup_field, например:

Вы можете создавать настраиваемые подклассы ModelSerializer или HyperlinkedModelSerializer, которые используют другой набор полей по умолчанию.

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

Динамическое изменение полей

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

Прямое изменение аргумента fields позволяет делать интересные вещи, например изменять аргументы полей сериализатора во время выполнения, а не в момент объявления сериализатора.

Пример

Например, если вы хотите указать, какие поля должны использоваться сериализатором в момент его инициализации, вы можете создать класс сериализатора следующим образом:

Это позволит вам сделать следующее:

Настройка полей по умолчанию

Атрибут field_mapping — это словарь, который сопоставляет классы модели с классами сериализатора. Переопределение атрибута позволит вам установить другой набор классов сериализатора по умолчанию.

Для более сложной настройки, чем просто изменение класса сериализатора по умолчанию, вы можете переопределить различные методы get_ _field. Это позволит вам настроить аргументы, с которыми инициализируется каждое поле сериализатора. Каждый из этих методов может либо возвращать поле или экземпляр сериализатора, либо None .

get_pk_field

Возвращает экземпляр поля, который должен использоваться для представления поля pk.

get_nested_field

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

Обратите внимание, что для обратных связей аргумент model_field будет равен None. Аргумент related_model будет классом модели для цели поля. Аргумент to_many будет логическим значением, указывающим, является ли это отношением к одному или ко многим.

get_related_field

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

Обратите внимание, что для обратных связей аргумент model_field будет равен None. Аргумент related_model будет классом модели для цели поля. Аргумент to_many будет логическим значением, указывающим, является ли это отношением к одному или ко многим.

получить_поле

Возвращает экземпляр поля, который следует использовать для нереляционных полей, отличных от pk.

Пример

Следующий пользовательский сериализатор модели можно использовать в качестве базового класса для сериализаторов моделей, которые по умолчанию всегда должны исключать pk.

Также доступны следующие сторонние пакеты.

Сериализатор модели Mongoengine

Пакет django-rest-framework-mongoengine предоставляет класс сериализатора MongoEngineModelSerializer, который поддерживает использование MongoDB в качестве уровня хранения для Django REST framework.

Сериализатор GeoFeatureModel

Пакет django-rest-framework-gis предоставляет класс сериализатора GeoFeatureModelSerializer, который поддерживает GeoJSON как для операций чтения, так и для записи.

Сериализатор HStore

Пакет django-rest-framework-hstore предоставляет HStoreSerializer для поддержки поля модели django-hstore DictionaryField и его функции режима схемы.

Сериализация преобразует данные в формат, который можно хранить или передавать, а затем восстанавливает их для использования. DRF имеет самые известные сериализаторы.

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

Предположим, вы создаете программное обеспечение для сайта электронной коммерции, и у вас есть Заказ, в котором регистрируется покупка одного продукта кем-то по цене в дату:

Представьте, что вы хотите хранить и извлекать данные о заказах из базы данных "ключ-значение". К счастью, его интерфейс принимает и возвращает словари, поэтому вам нужно преобразовать ваш объект в словарь:

И если вы хотите получить некоторые данные из этой базы данных, вы можете получить данные dict и превратить их в свой объект Order:

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

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

Django поставляется с модулем сериализации, который позволяет вам «переводить» модели в другие форматы:

Он охватывает наиболее часто используемые варианты веб-приложений, такие как JSON, YAML и XML. Но вы также можете использовать сторонние сериализаторы или создать свой собственный. Вам просто нужно зарегистрировать его в файле settings.py:

Чтобы создать собственный MyFormatSerializer , вам необходимо реализовать метод .serialize() и принять набор запросов и дополнительные параметры в качестве параметров:

Теперь вы можете сериализовать свой набор запросов в новый формат:

Вы можете использовать параметры options для определения поведения вашего сериализатора. Например, если вы хотите определить, что вы собираетесь работать с вложенной сериализацией при работе с ForeignKeys, или вы просто хотите, чтобы эти данные возвращали свои первичные ключи, вы можете передать параметр flat=True в качестве опции и обработать его внутри ваш метод:

Один из способов использования сериализации Django — это команды управления loaddata и dumpdata.

Сериализаторы DRF

В сообществе Django платформа Django REST (DRF) предлагает самые известные сериализаторы. Хотя вы можете использовать сериализаторы Django для создания JSON, на который вы будете отвечать в своем API, сериализатор из среды REST имеет удобные функции, которые помогут вам работать со сложными данными и легко проверять их.

В примере с Order вы можете создать такой сериализатор:

И легко сериализовать его данные:

Чтобы получить экземпляр из данных, необходимо реализовать два метода — create и update:

После этого вы можете создавать или обновлять экземпляры, вызывая is_valid() для проверки данных и save() для создания или обновления экземпляра:

Сериализаторы моделей

При сериализации данных вам часто нужно делать это из базы данных, следовательно, из ваших моделей. ModelSerializer, как и ModelForm, предоставляет API для создания сериализаторов из ваших моделей. Предположим, у вас есть модель Order:

Вы можете создать для него сериализатор следующим образом:

Django автоматически включает все поля модели в сериализатор и создает методы создания и обновления.

Использование сериализаторов в представлениях на основе классов (CBV)

Подобно формам с CBV Django, сериализаторы хорошо интегрируются с DRF. Вы можете установить атрибут serializer_class, чтобы сериализатор был доступен для представления:

Вы также можете определить метод get_serializer_class():

Программирование и разработка

В CBV есть и другие методы, взаимодействующие с сериализаторами. Например, get_serializer() возвращает уже созданный сериализатор, а get_serializer_context() возвращает аргументы, которые вы передадите сериализатору при создании его экземпляра. Для представлений, которые создают или обновляют данные, есть create и update, которые проверяют данные с помощью метода is_valid для сохранения, а также Perform_create и Perform_update, которые вызывают метод сохранения сериализатора.

Подробнее

Другие ресурсы см. на веб-сайте Classy Django REST Framework моего друга Андре Эриксона. Это версия REST Framework Classy-Based Views, которая дает вам всестороннюю проверку классов, составляющих DRF. Конечно, официальная документация — отличный ресурс.

Введение в структуру веб-приложений Django Python

В заключительной части серии, посвященной сравнению фреймворков Python, вы узнаете о Django.

Как написать веб-API Python с помощью Django

Django – одна из самых популярных платформ для разработки API Python. Узнайте, как его использовать, из этого краткого руководства.

Автор: Ник Томазич. Последнее обновление: 24 марта 2021 г.

Поделиться этим руководством

В этой статье мы на примере рассмотрим, как более эффективно использовать сериализаторы Django REST Framework (DRF). Попутно мы углубимся в некоторые дополнительные понятия, такие как использование исходного ключевого слова, передача контекста, проверка данных и многое другое.

В этой статье предполагается, что вы уже хорошо разбираетесь в Django REST Framework.

Содержание

Что покрывается?

В этой статье рассматриваются:

  1. Проверка данных на уровне поля или объекта
  2. Настройка вывода сериализации и десериализации
  3. Передача дополнительных данных при сохранении
  4. Передача контекста сериализаторам
  5. Переименование полей вывода сериализатора
  6. Присоединение ответов функции сериализатора к данным
  7. Извлечение данных из индивидуальных моделей
  8. Присоединение данных к сериализованному выводу
  9. Создание отдельных сериализаторов чтения и записи
  10. Настройка полей только для чтения
  11. Обработка вложенной сериализации

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

Пользовательская проверка данных

DRF обеспечивает проверку данных в процессе десериализации, поэтому вам необходимо вызвать is_valid() перед доступом к проверенным данным. Если данные недействительны, ошибки добавляются к свойству error сериализатора и выдается ValidationError.

Существует два типа пользовательских валидаторов данных:

Давайте рассмотрим пример. Предположим, у нас есть модель Movie:

У нашей модели есть название , описание , Release_date , рейтинг , US_gross и world_gross .

У нас также есть простой ModelSerializer, который сериализует все поля:

Допустим, модель действительна только в том случае, если верны оба этих условия:

  1. рейтинг от 1 до 10
  2. US_gross меньше, чем world_gross

Для этого мы можем использовать специальные средства проверки данных.

Проверка настраиваемого поля

Проверка настраиваемого поля позволяет нам проверять конкретное поле. Мы можем использовать его, добавив метод validate_ в наш сериализатор следующим образом:

Наш метод validate_rating следит за тем, чтобы рейтинг всегда оставался в диапазоне от 1 до 10.

Проверка на уровне объекта

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

Метод проверки гарантирует, что us_gross никогда не будет больше, чем world_gross .

Вам следует избегать доступа к дополнительным полям в валидаторе настраиваемых полей через self.initial_data . Этот словарь содержит необработанные данные, что означает, что ваши типы данных не обязательно будут соответствовать требуемым типам данных. DRF также добавит ошибки проверки в неверное поле.

Функциональные валидаторы

Если мы используем один и тот же валидатор в нескольких сериализаторах, мы можем создать функциональный валидатор вместо того, чтобы снова и снова писать один и тот же код. Давайте напишем валидатор, который проверяет, находится ли число в диапазоне от 1 до 10:

Теперь мы можем добавить его в наш MovieSerializer следующим образом:

Пользовательские выходные данные

Две наиболее полезные функции внутри класса BaseSerializer, которые мы можем переопределить, — это to_representation() и to_internal_value() . Переопределяя их, мы можем изменить поведение сериализации и десериализации соответственно, чтобы добавлять дополнительные данные, извлекать данные и обрабатывать отношения.

  1. to_representation() позволяет нам изменить вывод сериализации
  2. to_internal_value() позволяет нам изменить вывод десериализации

Предположим, у вас есть следующая модель:

У каждого ресурса есть заголовок , содержание и поле like_by. Liked_by представляет пользователей, которым понравился ресурс.

Наш сериализатор определен так:

Если мы сериализуем ресурс и получим доступ к его свойству данных, мы получим следующий вывод:

to_representation()

Теперь предположим, что мы хотим добавить общее количество лайков к сериализованным данным. Самый простой способ добиться этого — реализовать метод to_representation в нашем классе сериализатора:

Этот фрагмент кода извлекает текущее представление, добавляет к нему лайки и возвращает его.

Если мы сериализуем другой ресурс, то получим следующий результат:

to_internal_value()

Предположим, что службы, использующие наш API, добавляют ненужные данные к конечной точке при создании ресурсов:

Если мы попытаемся сериализовать эти данные, наш сериализатор выйдет из строя, поскольку он не сможет извлечь ресурс.

Мы можем переопределить to_internal_value() для извлечения данных ресурса:

Ура! Наш сериализатор теперь работает должным образом.

Сохранить сериализатор

Вызов save() либо создаст новый экземпляр, либо обновит существующий, в зависимости от того, был ли передан существующий экземпляр при создании экземпляра класса сериализатора:

Передача данных напрямую для сохранения

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

Это можно сделать, включив дополнительные аргументы ключевого слова при вызове save() . Например:

Имейте в виду, что значения, переданные в save(), не будут проверены.

Контекст сериализатора

В некоторых случаях вам необходимо передать дополнительные данные вашим сериализаторам. Вы можете сделать это, используя свойство контекста сериализатора. Затем вы можете использовать эти данные внутри сериализатора, такого как to_representation, или при проверке данных.

Вы передаете данные как словарь через ключевое слово контекста:

Затем вы можете получить его внутри класса сериализатора из словаря self.context следующим образом:

Вывод нашего сериализатора теперь будет содержать ключ со значением .

Исходное ключевое слово

Сериализатор DRF поставляется с ключевым словом source, которое является чрезвычайно мощным и может использоваться в различных сценариях. Мы можем использовать его для:

  1. Переименовать выходные поля сериализатора
  2. Прикрепить ответ функции сериализатора к данным
  3. Извлечение данных из индивидуальных моделей

Допустим, вы создаете социальную сеть, и у каждого пользователя есть собственный UserProfile , который напрямую связан с моделью User:

Мы используем ModelSerializer для сериализации наших пользователей:

Давайте сериализуем пользователя:

Переименовать выходные поля сериализатора

Чтобы переименовать поле вывода сериализатора, нам нужно добавить новое поле в наш сериализатор и передать его свойству fields.

Наше активное поле теперь будет называться active вместо is_active .

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

Мы можем использовать источник, чтобы добавить поле, равное возвращаемой функции.

get_full_name() — это метод пользовательской модели Django, который объединяет user.first_name и user.last_name .

Теперь наш ответ будет содержать full_name .

Добавление данных из моделей "один к одному"

Теперь давайте предположим, что мы также хотим включить биографию нашего пользователя и дату рождения в UserSerializer . Мы можем сделать это, добавив дополнительные поля в наш сериализатор с ключевым словом source.

Давайте изменим наш класс сериализатора:

Мы можем получить доступ к профилю пользователя. , потому что это отношение один к одному с нашим пользователем.

Это наш окончательный ответ в формате JSON:

SerializerMethodField

SerializerMethodField — это поле, доступное только для чтения, которое получает свое значение путем вызова метода в классе сериализатора, к которому оно прикреплено. Его можно использовать для присоединения любых данных к сериализованному представлению объекта.

SerializerMethodField получает данные, вызывая get_ .

Если бы мы хотели добавить атрибут full_name в наш сериализатор User, мы могли бы добиться этого следующим образом:

Этот фрагмент кода создает пользовательский сериализатор, который также содержит full_name, являющийся результатом функции get_full_name().

Различные сериализаторы чтения и записи

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

Вы делаете это, переопределяя метод get_serializer_class() в своем ViewSet следующим образом:

Этот код проверяет, какая операция REST была использована, и возвращает MyModelWriteSerializer для операций записи и MyModelReadSerializer для операций чтения.

Поля только для чтения

Поля сериализатора поставляются с параметром только для чтения. Установив значение True , DRF включает поле в выходные данные API, но игнорирует его во время операций создания и обновления:

Настройка таких полей, как id , create_date и т. д., только для чтения, повысит производительность во время операций записи.

Если вы хотите установить несколько полей в read_only , вы можете указать их с помощью read_only_fields в метаданных следующим образом:

Вложенные сериализаторы

Существует два разных способа обработки вложенной сериализации с помощью ModelSerializer:

  1. Явное определение
  2. Использование поля глубины

Явное определение

Явное определение работает, передавая внешний сериализатор как поле нашему основному сериализатору.

Давайте рассмотрим пример. У нас есть комментарий, который определяется следующим образом:

Скажем, у вас есть следующий сериализатор:

Если мы сериализуем Comment , вы получите следующий результат:

Если мы также хотим сериализовать пользователя (вместо того, чтобы показывать только его идентификатор), мы можем добавить поле авторского сериализатора в наш комментарий:

Выполните сериализацию еще раз, и вы получите следующее:

Использование поля глубины

Когда дело доходит до вложенной сериализации, поле глубины является одной из самых мощных функций. Предположим, у нас есть три модели — ModelA, ModelB и ModelC. ModelA зависит от ModelB, а ModelB зависит от ModelC. Они определяются следующим образом:

Наш сериализатор ModelA, который является объектом верхнего уровня, выглядит следующим образом:

Если мы сериализуем пример объекта, мы получим следующий результат:

Теперь предположим, что мы также хотим включить содержимое ModelB при сериализации ModelA. Мы могли бы добавить явное определение в наш ModelASerializer или использовать поле глубины.

Когда мы меняем глубину на 1 в нашем сериализаторе следующим образом:

Вывод изменится на следующий:

Если мы изменим его на 2, наш сериализатор будет сериализовать уровень глубже:

Недостаток в том, что вы не можете контролировать сериализацию дочерних элементов. Другими словами, использование depth будет включать все поля дочерних элементов.

Заключение

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

Кратко о том, что конкретно мы рассмотрели:

Концепция Метод
Проверка данных на уровне поля или объекта validate_ or validate
Настройка вывода сериализации и десериализации to_representation и to_internal_value
Передача дополнительных данных при сохранении serializer.save(additional=data)
Передача контекста сериализаторам SampleSerializer (resource, context=)
Переименование полей вывода сериализатора исходное ключевое слово
Присоединение функции сериализатора ответы на данные исходное ключевое слово
Извлечение данных из моделей один к одному исходное ключевое слово
Присоединение данных к сериализованному выводу SerializerMethodField
Создание отдельных сериализаторов чтения и записи get_serializer_class ()
Настройка полей только для чтения read_only_fields
Обработка вложенная сериализация поле глубины

Ник Томазич

Ник – разработчик программного обеспечения из Словении. Он интересуется объектно-ориентированным программированием и веб-разработкой. Ему нравится узнавать новое и принимать новые вызовы. Когда Ник не программирует, он либо плавает, либо смотрит фильмы.

Поделиться этим руководством

Поделиться этим руководством

Разработка через тестирование с использованием Django, Django REST Framework и Docker

В этом курсе вы узнаете, как настроить среду разработки с помощью Docker, чтобы создать и развернуть RESTful API на основе Python, Django и Django REST Framework.

Темы руководства

Содержание

Разработка через тестирование с использованием Django, Django REST Framework и Docker

В этом курсе вы узнаете, как настроить среду разработки с помощью Docker, чтобы создать и развернуть RESTful API на основе Python, Django и Django REST Framework.

Читайте также: