Сериализаторы
источник:
serializers.py
Сериализаторы
Расширение полезности сериализаторов - это то, чем мы хотели бы заняться. Однако это не тривиальная проблема, и она потребует серьезной работы над дизайном.
— Russell Keith-Magee, Django users group
Сериализаторы позволяют преобразовывать сложные данные, такие как наборы запросов и экземпляры моделей, в собственные типы данных Python, которые затем могут быть легко преобразованы в JSON
, XML
или другие типы содержимого. Сериализаторы также обеспечивают десериализацию, позволяя преобразовывать разобранные данные обратно в сложные типы после предварительной проверки входящих данных.
Сериализаторы в DRF работают очень похоже на классы Django Form
и ModelForm
. Мы предоставляем класс Serializer
, который дает вам мощный, универсальный способ управления выводом ваших ответов, а также класс ModelSerializer
, который предоставляет полезный ярлык для создания сериализаторов, работающих с экземплярами моделей и наборами запросов.
Объявление сериализаторов
Давайте начнем с создания простого объекта, который мы можем использовать для примера:
Мы объявим сериализатор, который мы можем использовать для сериализации и десериализации данных, соответствующих объектам Comment
.
Объявление сериализатора очень похоже на объявление формы:
Сериализация объектов
Теперь мы можем использовать CommentSerializer
для сериализации комментария или списка комментариев. Опять же, использование класса Serializer
очень похоже на использование класса Form
.
На данном этапе мы перевели экземпляр модели в собственные типы данных Python. Чтобы завершить процесс сериализации, мы преобразуем данные в json
.
Десериализация объектов
Десериализация аналогична. Сначала мы разбираем поток на собственные типы данных Python...
затем мы восстанавливаем эти родные типы данных в словарь проверенных данных.
Сохранение экземпляров
Если мы хотим иметь возможность возвращать полные экземпляры объектов на основе проверенных данных, нам необходимо реализовать один или оба метода .create()
и .update()
. Например:
Если ваши экземпляры объектов соответствуют моделям Django, вы также захотите убедиться, что эти методы сохраняют объект в базе данных. Например, если Comment
является моделью Django, методы могут выглядеть следующим образом:
Теперь при десериализации данных мы можем вызвать .save()
, чтобы вернуть экземпляр объекта, основанный на проверенных данных.
Вызов .save()
либо создаст новый экземпляр, либо обновит существующий, в зависимости от того, был ли передан существующий экземпляр при инстанцировании класса сериализатора:
Методы .create()
и .update()
являются необязательными. Вы можете реализовать либо ни один из них, либо один, либо оба, в зависимости от условий использования вашего класса сериализатора.
Передача дополнительных атрибутов в .save()
.
Иногда вы хотите, чтобы код представления мог вводить дополнительные данные в момент сохранения экземпляра. Эти дополнительные данные могут включать информацию о текущем пользователе, текущем времени или что-нибудь еще, что не является частью данных запроса.
Вы можете сделать это, включив дополнительные именованные аргументы при вызове .save()
. Например:
Любые дополнительные именованные аргументы будут включены в аргумент validated_data
при вызове .create()
или .update()
.
Переопределение .save()
напрямую.
В некоторых случаях имена методов .create()
и .update()
могут не иметь смысла. Например, в контактной форме мы можем не создавать новые экземпляры, а отправлять электронное письмо или другое сообщение.
В этих случаях вы можете вместо этого переопределить .save()
напрямую, как более читабельный и осмысленный.
Например:
Обратите внимание, что в приведенном выше случае нам приходится напрямую обращаться к свойству сериализатора .validated_data
.
Валидация
При десериализации данных всегда нужно вызывать is_valid()
прежде, чем пытаться получить доступ к проверенным данным или сохранить экземпляр объекта. Если возникнут ошибки валидации, свойство .errors
будет содержать словарь, представляющий сообщения об ошибках. Например:
Каждый ключ в словаре будет именем поля, а значения будут списками строк любых сообщений об ошибках, соответствующих этому полю. Также может присутствовать ключ non_field_errors
, в котором будут перечислены все общие ошибки валидации. Имя ключа non_field_errors
можно настроить с помощью параметра DRF NON_FIELD_ERRORS_KEY
.
При десериализации списка элементов ошибки будут возвращены в виде списка словарей, представляющих каждый из десериализованных элементов.
Возбуждение исключения при недопустимых данных
Метод .is_valid()
принимает необязательный флаг raise_exception
, который заставит его поднять исключение serializers.ValidationError
, если есть ошибки валидации.
Эти исключения автоматически обрабатываются обработчиком исключений по умолчанию, который предоставляет DRF, и по умолчанию будут возвращать ответы HTTP 400 Bad Request
.
Валидация на уровне поля
Вы можете задать пользовательскую валидацию на уровне полей, добавив методы .validate_<имя_поля>
в подкласс Serializer
. Они аналогичны методам .clean_<имя_поля>
в формах Django.
Эти методы принимают единственный аргумент, который является значением поля, требующего проверки.
Ваши методы validate_<имя_поля>
должны возвращать проверенное значение или вызывать serializers.ValidationError
. Например:
Примечание: Если ваше <имя_поля>
объявлено в вашем сериализаторе с параметром required=False
, то этот шаг валидации не будет выполняться, если поле не включено.
Валидация на уровне объекта
Чтобы выполнить любую другую проверку, требующую доступа к нескольким полям, добавьте метод .validate()
к вашему подклассу Serializer
. Этот метод принимает единственный аргумент, который является словарем значений полей. При необходимости он должен вызывать `serializers.ValidationError, или просто возвращать проверенные значения. Например:
Валидаторы
Отдельные поля сериализатора могут включать валидаторы, например, путем объявления их в экземпляре поля:
Классы сериализаторов могут также включать многократно используемые валидаторы, которые применяются к полному набору данных поля. Эти валидаторы включаются путем объявления их во внутреннем классе Meta
, например, так:
Для получения дополнительной информации см. документацию validators.
Доступ к исходным данным и экземпляру
При передаче исходного объекта или набора запросов экземпляру сериализатора, объект будет доступен как .instance
. Если начальный объект не передан, то атрибут .instance
будет иметь значение None
.
При передаче данных экземпляру сериализатора, немодифицированные данные будут доступны как .initial_data
. Если именованный аргумент data
не передан, то атрибут .initial_data
не будет существовать.
Частичные обновления
По умолчанию сериализаторам должны передаваться значения для всех обязательных полей, иначе они будут выдавать ошибки валидации. Вы можете использовать аргумент partial
, чтобы разрешить частичное обновление.
Работа с вложенными объектами
Предыдущие примеры хорошо подходят для работы с объектами, которые имеют только простые типы данных, но иногда нам также необходимо иметь возможность представлять более сложные объекты, где некоторые атрибуты объекта могут не быть простыми типами данных, такими как строки, даты или целые числа.
Класс Serializer
сам является типом Field
и может быть использован для представления отношений, в которых один тип объекта вложен в другой.
Если вложенное представление может опционально принимать значение None
, вы должны передать флаг required=False
вложенному сериализатору.
Аналогично, если вложенное представление должно быть списком элементов, вы должны передать флаг many=True
в сериализатор вложенных элементов.
Записываемые вложенные представления
При работе с вложенными представлениями, поддерживающими десериализацию данных, любые ошибки с вложенными объектами будут вложены под именем поля вложенного объекта.
Аналогично, свойство .validated_data
будет включать в себя вложенные структуры данных.
Написание методов .create()
для вложенных представлений
Если вы поддерживаете записываемые вложенные представления, вам нужно написать методы .create()
или .update()
, которые обрабатывают сохранение нескольких объектов.
В следующем примере показано, как можно создать пользователя с вложенным объектом профиля.
Написание методов .update()
для вложенных представлений
Для обновлений вам необходимо тщательно продумать, как обрабатывать обновления отношений. Например, если данные для отношения None
, или не предоставлены, что из перечисленного ниже должно произойти?
Установите для отношения значение
NULL
в базе данных.Удалите связанный экземпляр.
Игнорировать данные и оставить экземпляр как есть.
Вызвать ошибку валидации.
Вот пример метода .update()
для нашего предыдущего класса UserSerializer
.
Поскольку поведение вложенных созданий и обновлений может быть неоднозначным и может требовать сложных зависимостей между связанными моделями, DRF 3 требует, чтобы вы всегда писали эти методы явно. Методы ModelSerializer
.create()
и .update()
по умолчанию не включают поддержку записываемых вложенных представлений.
Однако существуют сторонние пакеты, такие как DRF Writable Nested, которые поддерживают автоматические записываемые вложенные представления.
Обработка сохранения связанных экземпляров в классах менеджера моделей
Альтернативой сохранению нескольких связанных экземпляров в сериализаторе является написание пользовательских классов менеджера модели, которые занимаются созданием нужных экземпляров.
Например, предположим, мы хотим, чтобы экземпляры User
и Profile
всегда создавались вместе как пара. Мы можем написать пользовательский класс менеджера, который будет выглядеть примерно так:
Этот класс менеджера теперь более точно передает, что экземпляры пользователя и профиля всегда создаются одновременно. Наш метод .create()
в классе сериализатора теперь может быть переписан для использования нового метода менеджера.
Более подробно об этом подходе смотрите документацию Django по менеджерам моделей, и этот блогпост об использовании классов моделей и менеджеров.
Работа с несколькими объектами
Класс Serializer
также может обрабатывать сериализацию или десериализацию списков объектов.
Сериализация нескольких объектов
Чтобы сериализовать кверисет или список объектов вместо одного экземпляра объекта, необходимо передать флаг many=True
при инстанцировании сериализатора. Затем вы можете передать кверисет или список объектов для сериализации.
Десериализация нескольких объектов
Поведение по умолчанию для десериализации нескольких объектов - это поддержка создания нескольких объектов, но не поддержка обновления нескольких объектов. Для получения дополнительной информации о том, как поддержать или настроить любой из этих случаев, см. документацию по ListSerializer ниже.
Включение дополнительного контекста
Бывают случаи, когда вам необходимо предоставить сериализатору дополнительный контекст в дополнение к сериализуемому объекту. Одним из распространенных случаев является использование сериализатора, который включает отношения с гиперссылками, что требует, чтобы сериализатор имел доступ к текущему запросу, чтобы он мог правильно генерировать полностью определенные URL.
Вы можете предоставить произвольный дополнительный контекст, передав аргумент context
при инстанцировании сериализатора. Например:
Контекстный словарь можно использовать в любой логике поля сериализатора, например, в пользовательском методе .to_representation()
, обращаясь к атрибуту self.context
.
ModelSerializer
Часто вам понадобятся классы сериализаторов, которые близко сопоставляются с определениями моделей Django.
Класс ModelSerializer
предоставляет ярлык, позволяющий автоматически создать класс Serializer
с полями, соответствующими полям модели.
Класс ModelSerializer
такой же, как и обычный класс Serializer
, за исключением того, что:
Он автоматически сгенерирует для вас набор полей на основе модели.
Он автоматически генерирует валидаторы для сериализатора, такие как валидаторы unique_together.
Он включает простые реализации по умолчанию
.create()
и.update()
.
Объявление ModelSerializer
выглядит следующим образом:
По умолчанию все поля модели класса будут отображены на соответствующие поля сериализатора.
Любые отношения, такие как внешние ключи в модели, будут отображены на PrimaryKeyRelatedField
. Обратные отношения не включаются по умолчанию, если они не включены явно, как указано в документации serializer relations.
Проверка ModelSerializer
.
Классы сериализаторов генерируют полезные строки представления, которые позволяют полностью просмотреть состояние их полей. Это особенно полезно при работе с ModelSerializers
, когда вы хотите определить, какой набор полей и валидаторов автоматически создается для вас.
Для этого откройте оболочку Django, используя python manage.py shell
, затем импортируйте класс сериализатора, инстанцируйте его и выведите представление объекта...
Указание, какие поля включать
Если вы хотите, чтобы в сериализаторе модели использовалось только подмножество полей по умолчанию, вы можете сделать это с помощью опций fields
или exclude
, как и в случае с ModelForm
. Настоятельно рекомендуется явно задавать все поля, которые должны быть сериализованы, с помощью атрибута fields
. Это уменьшит вероятность непреднамеренного раскрытия данных при изменении ваших моделей.
Например:
Вы также можете установить для атрибута fields
специальное значение '__all__'
, чтобы указать, что должны использоваться все поля в модели.
Например:
Вы можете установить атрибут exclude
в список полей, которые должны быть исключены из сериализатора.
Например:
В приведенном выше примере, если модель Account
имеет 3 поля account_name
, users
и created
, это приведет к тому, что поля account_name
и created
будут сериализованы.
Имена в атрибутах fields
и exclude
обычно отображаются на поля модели в классе модели.
Альтернативные имена в опциях fields
могут отображаться на свойства или методы, не принимающие аргументов, которые существуют в классе модели.
Начиная с версии 3.3.0, обязательным является предоставление одного из атрибутов fields
или exclude
.
Указание вложенной сериализации
По умолчанию ModelSerializer
использует первичные ключи для отношений, но вы также можете легко генерировать вложенные представления с помощью опции depth
:
Параметр depth
должен быть установлен в целочисленное значение, которое указывает глубину отношений, которые должны быть пройдены перед возвратом к плоскому представлению.
Если вы хотите настроить способ сериализации, вам нужно будет определить поле самостоятельно.
Указание полей в явном виде
Вы можете добавить дополнительные поля в ModelSerializer
или переопределить поля по умолчанию, объявив поля в классе, как и в классе Serializer
.
Дополнительные поля могут соответствовать любому свойству или вызываемому объекту модели.
Указание полей, доступных только для чтения
Вы можете указать несколько полей как доступные только для чтения. Вместо того чтобы добавлять каждое поле явно с атрибутом read_only=True
, вы можете использовать сокращенную опцию Meta, read_only_fields
.
Этот параметр должен представлять собой список или кортеж имен полей и объявляется следующим образом:
Поля модели, для которых установлено значение editable=False
, и поля AutoField
по умолчанию будут установлены в режим только для чтения, и их не нужно добавлять в опцию read_only_fields
.
Примечание: Существует особый случай, когда поле, доступное только для чтения, является частью ограничения unique_together
на уровне модели. В этом случае поле требуется классу сериализатора для проверки ограничения, но также не должно редактироваться пользователем.
Правильный способ справиться с этим - явно указать поле в сериализаторе, предоставив именованные аргументы read_only=True
и default=...
.
Одним из примеров этого является отношение только для чтения к текущему аутентифицированному User
, который является unique_together
с другим идентификатором. В этом случае вы объявите поле пользователя следующим образом:
Пожалуйста, ознакомьтесь с документацией Validators Documentation для получения подробной информации о классах UniqueTogetherValidator и CurrentUserDefault.
Дополнительные именованные аргументы
Также есть возможность указать произвольные дополнительные именованные аргументы для полей, используя опцию extra_kwargs
. Как и в случае с read_only_fields
, это означает, что вам не нужно явно объявлять поле в сериализаторе.
Эта опция представляет собой словарь, отображающий имена полей на словарь именованных аргументов. Например:
Следует помнить, что если поле уже было явно объявлено в классе сериализатора, то опция extra_kwargs
будет проигнорирована.
Реляционные поля
При сериализации экземпляров модели существует несколько различных способов представления отношений. Представление по умолчанию для ModelSerializer
заключается в использовании первичных ключей связанных экземпляров.
Альтернативные представления включают сериализацию с помощью гиперссылок, сериализацию полных вложенных представлений или сериализацию с помощью пользовательского представления.
Более подробную информацию можно найти в документации serializer relations.
Настройка сопоставлений полей
Класс ModelSerializer также предоставляет API, который вы можете переопределить, чтобы изменить способ автоматического определения полей сериализатора при инстанцировании сериализатора.
Обычно, если ModelSerializer
не генерирует нужные вам поля по умолчанию, вы должны либо добавить их в класс явно, либо просто использовать вместо них обычный класс Serializer
. Однако в некоторых случаях вы можете захотеть создать новый базовый класс, определяющий, как создаются поля сериализатора для любой конкретной модели.
serializer_field_mapping
.
serializer_field_mapping
.Отображение полей модели Django на поля сериализатора DRF. Вы можете переопределить это отображение, чтобы изменить поля сериализатора по умолчанию, которые должны использоваться для каждого поля модели.
serializer_related_field
.
serializer_related_field
.Это свойство должно быть классом поля сериализатора, который по умолчанию используется для реляционных полей.
Для ModelSerializer
это значение по умолчанию равно serializers.PrimaryKeyRelatedField
.
Для HyperlinkedModelSerializer
это значение по умолчанию равно serializers.HyperlinkedRelatedField
.
serializer_url_field
.
serializer_url_field
.Класс поля сериализатора, который должен использоваться для любого поля url
в сериализаторе.
По умолчанию serializers.HyperlinkedIdentityField
.
serializer_choice_field
serializer_choice_field
Класс поля сериализатора, который должен использоваться для любых полей выбора в сериализаторе.
По умолчанию serializers.ChoiceField
.
API field_class и field_kwargs
Следующие методы вызываются для определения класса и именованных аргументов для каждого поля, которое должно быть автоматически включено в сериализатор. Каждый из этих методов должен возвращать кортеж (field_class, field_kwargs)
.
build_standard_field(self, field_name, model_field)
.
build_standard_field(self, field_name, model_field)
.Вызывается для генерации поля сериализатора, которое сопоставляется со стандартным полем модели.
Реализация по умолчанию возвращает класс сериализатора на основе атрибута serializer_field_mapping
.
build_relational_field(self, field_name, relation_info)
.
build_relational_field(self, field_name, relation_info)
.Вызывается для генерации поля сериализатора, которое сопоставляется с полем реляционной модели.
Реализация по умолчанию возвращает класс сериализатора на основе атрибута serializer_related_field
.
Аргумент relation_info
представляет собой именованный кортеж, содержащий свойства model_field
, related_model
, to_many
и has_through_model
.
build_nested_field(self, field_name, relation_info, nested_depth)
.
build_nested_field(self, field_name, relation_info, nested_depth)
.Вызывается для генерации поля сериализатора, которое сопоставляется с полем реляционной модели, если установлен параметр depth
.
Реализация по умолчанию динамически создает вложенный класс сериализатора на основе ModelSerializer
или HyperlinkedModelSerializer
.
Значение nested_depth
будет равно значению опции depth
, минус один.
Аргумент relation_info
представляет собой именованный кортеж, содержащий свойства model_field
, related_model
, to_many
и has_through_model
.
build_property_field(self, field_name, model_class)
.
build_property_field(self, field_name, model_class)
.Вызывается для генерации поля сериализатора, которое сопоставляется со свойством или методом с нулевым аргументом класса модели.
Реализация по умолчанию возвращает класс ReadOnlyField
.
build_url_field(self, field_name, model_class)
.
build_url_field(self, field_name, model_class)
.Вызывается для генерации поля сериализатора для собственного поля сериализатора url
. Реализация по умолчанию возвращает класс HyperlinkedIdentityField
.
build_unknown_field(self, field_name, model_class)
.
build_unknown_field(self, field_name, model_class)
.Вызывается, когда имя поля не сопоставлено ни с одним полем модели или свойством модели. Реализация по умолчанию вызывает ошибку, хотя подклассы могут настраивать это поведение.
HyperlinkedModelSerializer
Класс HyperlinkedModelSerializer
похож на класс ModelSerializer
, за исключением того, что он использует гиперссылки для представления отношений, а не первичные ключи.
По умолчанию сериализатор будет включать поле url
вместо поля первичного ключа.
Поле url будет представлено с помощью поля сериализатора HyperlinkedIdentityField
, а любые отношения в модели будут представлены с помощью поля сериализатора HyperlinkedRelatedField
.
Вы можете явно включить первичный ключ, добавив его, например, в опцию fields
:
Абсолютные и относительные URL-адреса
При инстанцировании HyperlinkedModelSerializer
вы должны включить текущий request
в контекст сериализатора, например:
Это гарантирует, что гиперссылки будут содержать соответствующее имя хоста, чтобы в результирующем представлении использовались полные URL-адреса, например:
Вместо относительных URL-адресов, таких как:
Если вы хотите использовать относительные URL, вы должны явно передать {'request': None}
в контексте сериализатора.
Как определяются представления с гиперссылками
Необходимо определить, какие представления следует использовать для гиперссылок на экземпляры модели.
По умолчанию ожидается, что гиперссылки будут соответствовать имени представления, которое соответствует стилю '{имя_модели}-detail'
, и ищет экземпляр по именованному аргументу pk
.
Вы можете переопределить имя представления поля URL и поле поиска, используя один или оба параметра view_name
и lookup_field
в параметре extra_kwargs
, как показано ниже:
В качестве альтернативы вы можете явно задать поля в сериализаторе. Например:
Совет: Правильное согласование гиперссылочных представлений и вашего URL conf иногда может быть немного сложным. Печать repr
экземпляра HyperlinkedModelSerializer
- особенно полезный способ проверить, какие именно имена представлений и поля поиска должны отображать отношения.
Изменение имени поля URL
Имя поля URL по умолчанию равно 'url'. Вы можете переопределить его глобально, используя параметр URL_FIELD_NAME
.
ListSerializer
Класс ListSerializer
обеспечивает поведение для сериализации и валидации нескольких объектов одновременно. Обычно вам не нужно использовать ListSerializer
напрямую, а следует просто передать many=True
при инстанцировании сериализатора.
При инстанцировании сериализатора и передаче many=True
будет создан экземпляр ListSerializer
. Затем класс сериализатора становится дочерним классом родительского ListSerializer
.
Следующий аргумент также может быть передан полю ListSerializer
или сериализатору, которому передано many=True
:
allow_empty
allow_empty
По умолчанию это True
, но может быть установлено в False
, если вы хотите запретить пустые списки в качестве допустимого ввода.
max_length
max_length
По умолчанию это None
, но может быть установлено в положительное целое число, если вы хотите проверить, что список содержит не более этого количества элементов.
min_length
min_length
По умолчанию это None
, но может быть установлено в положительное целое число, если вы хотите проверить, что список содержит не менее этого количества элементов.
Настройка поведения ListSerializer
.
ListSerializer
.Существует несколько случаев, когда вы захотите настроить поведение ListSerializer
. Например:
Вы хотите обеспечить определенную проверку списков, например, проверить, что один элемент не конфликтует с другим элементом списка.
Вы хотите настроить поведение создания или обновления нескольких объектов.
Для этих случаев вы можете изменить класс, который используется при передаче many=True
, используя опцию list_serializer_class
для класса сериализатора Meta
.
Например:
Настройка множественного создания
Реализация по умолчанию для создания нескольких объектов заключается в простом вызове .create()
для каждого элемента списка. Если вы хотите настроить это поведение, вам нужно настроить метод .create()
класса ListSerializer
, который используется, когда передается many=True
.
Например:
Настройка многократного обновления
По умолчанию класс ListSerializer
не поддерживает множественные обновления. Это связано с тем, что поведение, которое следует ожидать для вставок и удалений, неоднозначно.
Для поддержки нескольких обновлений необходимо сделать это явно. При написании кода множественных обновлений обязательно учитывайте следующее:
Как определить, какой экземпляр должен быть обновлен для каждого элемента в списке данных?
Как следует обрабатывать вставки? Являются ли они недействительными, или они создают новые объекты?
Как следует обрабатывать удаления? Означают ли они удаление объекта или удаление отношения? Следует ли их молча игнорировать, или они недействительны?
Как следует обрабатывать упорядочивание? Влечет ли изменение положения двух объектов изменение состояния или оно игнорируется?
Вам нужно будет добавить явное поле id
в сериализатор экземпляра. По умолчанию неявно генерируемое поле id
помечено как read_only
. Это приводит к тому, что оно удаляется при обновлении. Как только вы объявите его явно, оно будет доступно в методе update
сериализатора списка.
Вот пример того, как можно реализовать несколько обновлений:
Настройка инициализации ListSerializer
Когда инстанцируется сериализатор с many=True
, нам необходимо определить, какие аргументы и ключевые слова следует передать в метод .__init__()
как для дочернего класса Serializer
, так и для родительского класса ListSerializer
.
По умолчанию все аргументы передаются обоим классам, за исключением validators
и любых пользовательских именованных аргументов, которые, как предполагается, предназначены для дочернего класса сериализатора.
Иногда вам может понадобиться явно указать, как дочерний и родительский классы должны быть инстанцированы при передаче many=True
. Вы можете сделать это с помощью метода класса many_init
.
BaseSerializer
Класс BaseSerializer
, который можно использовать для простой поддержки альтернативных стилей сериализации и десериализации.
Этот класс реализует тот же базовый API, что и класс Serializer
:
.data
- Возвращает исходящее примитивное представление..is_valid()
- Десериализует и проверяет входящие данные..validated_data
- Возвращает проверенные входящие данные..errors
- Возвращает любые ошибки во время валидации..save()
- Сохраняет проверенные данные в экземпляре объекта.
Есть четыре метода, которые могут быть переопределены, в зависимости от того, какую функциональность вы хотите, чтобы поддерживал класс сериализатора:
.to_representation()
- Переопределить это для поддержки сериализации, для операций чтения..to_internal_value()
- Переопределить это для поддержки десериализации, для операций записи..create()
и.update()
- Переопределите один из этих параметров или оба для поддержки сохранения экземпляров.
Поскольку этот класс предоставляет тот же интерфейс, что и класс Serializer
, вы можете использовать его с существующими общими представлениями на основе классов точно так же, как и обычный Serializer
или ModelSerializer
.
Единственное отличие, которое вы заметите при этом - классы BaseSerializer
не будут генерировать HTML-формы в Web-интерфейсе API. Это происходит потому, что данные, которые они возвращают, не включают всю информацию о полях, которая позволит преобразовать каждое поле в подходящий HTML-ввод.
Классы BaseSerializer
только для чтения.
Чтобы реализовать сериализатор только для чтения, используя класс BaseSerializer
, нам просто нужно переопределить метод .to_representation()
. Давайте рассмотрим пример на примере простой модели Django:
Очень просто создать сериализатор только для чтения для преобразования экземпляров HighScore
в примитивные типы данных.
Теперь мы можем использовать этот класс для сериализации отдельных экземпляров HighScore
:
Или используйте его для сериализации нескольких экземпляров:
Классы BaseSerializer
с функцией чтения-записи
Для создания сериализатора чтения-записи нам сначала нужно реализовать метод .to_internal_value()
. Этот метод возвращает проверенные значения, которые будут использованы для создания экземпляра объекта, и может вызвать serializers.ValidationError
, если предоставленные данные имеют неправильный формат.
Как только вы реализуете .to_internal_value()
, базовый API валидации будет доступен в сериализаторе, и вы сможете использовать .is_valid()
, .validated_data
и .errors
.
Если вы хотите также поддерживать .save()
, вам необходимо также реализовать один или оба метода .create()
и .update()
.
Вот полный пример нашего предыдущего HighScoreSerializer
, который был обновлен для поддержки операций чтения и записи.
Создание новых базовых классов
Класс BaseSerializer
также полезен, если вы хотите реализовать новые общие классы сериализаторов для работы с определенными стилями сериализации или для интеграции с альтернативными бэкендами хранения данных.
Следующий класс является примером общего сериализатора, который может обрабатывать принудительное преобразование произвольных сложных объектов в примитивные представления.
Расширенное использование сериализатора
Переопределение поведения сериализации и десериализации
Если вам нужно изменить поведение сериализации или десериализации класса сериализатора, вы можете сделать это, переопределив методы .to_representation()
или .to_internal_value()
.
Некоторые причины, по которым это может быть полезно, включают...
Добавление нового поведения для новых базовых классов сериализаторов.
Небольшое изменение поведения для существующего класса.
Улучшение производительности сериализации для часто используемой конечной точки API, которая возвращает много данных.
Подписи для этих методов следующие:
to_representation(self, instance)
.
Принимает экземпляр объекта, который требует сериализации, и должен вернуть примитивное представление. Обычно это означает возврат структуры встроенных в Python типов данных. Точные типы, которые могут быть обработаны, зависят от классов рендеринга, которые вы настроили для своего API.
Может быть переопределена для изменения стиля представления. Например:
to_internal_value(self, data)
.
Принимает невалидированные входящие данные в качестве входных и должен вернуть валидированные данные, которые будут доступны как serializer.validated_data
. Возвращаемое значение также будет передано в методы .create()
или .update()
, если для класса сериализатора будет вызван .save()
.
Если какая-либо из валидаций не прошла, то метод должен вызвать serializers.ValidationError(errors)
. Аргумент errors
должен представлять собой словарь, отображающий имена полей (или settings.NON_FIELD_ERRORS_KEY
) на список сообщений об ошибках. Если вам не нужно изменять поведение десериализации и вместо этого вы хотите обеспечить проверку на уровне объекта, рекомендуется переопределить метод .validate()
.
Аргумент data
, передаваемый этому методу, обычно является значением request.data
, поэтому тип данных, который он предоставляет, будет зависеть от классов парсера, которые вы настроили для своего API.
Наследование сериализатора
Подобно формам Django, вы можете расширять и повторно использовать сериализаторы с помощью наследования. Это позволяет вам объявить общий набор полей или методов в родительском классе, который затем может быть использован в нескольких сериализаторах. Например,
Как и классы Model
и ModelForm
в Django, внутренний класс Meta
в сериализаторах не наследуется неявно от внутренних классов Meta
своих родителей. Если вы хотите, чтобы класс Meta
наследовался от родительского класса, вы должны сделать это явно. Например:
Обычно мы рекомендуем не использовать наследование для внутренних классов Meta, а вместо этого объявлять все опции явно.
Кроме того, следующие предостережения относятся к наследованию сериализаторов:
Применяются обычные правила разрешения имен Python. Если у вас есть несколько базовых классов, которые объявляют внутренний класс
Meta
, будет использоваться только первый класс. Это означает дочернийMeta
, если он существует, иначеMeta
первого родителя и т.д.Можно декларативно удалить
Field
, унаследованный от родительского класса, указав значениеNone
в подклассе.
Однако вы можете использовать эту технику только для отказа от поля, определенного декларативно родительским классом; это не помешает ModelSerializer
сгенерировать поле по умолчанию. Чтобы отказаться от полей по умолчанию, смотрите Указание, какие поля включать.
Динамическое изменение полей
После инициализации сериализатора, к словарю полей, установленных в сериализаторе, можно получить доступ с помощью атрибута .fields
. Доступ и изменение этого атрибута позволяет динамически модифицировать сериализатор.
Изменение аргумента fields
напрямую позволяет вам делать такие интересные вещи, как изменение аргументов полей сериализатора во время выполнения, а не в момент объявления сериализатора.
Пример
Например, если вы хотите иметь возможность установить, какие поля должны использоваться сериализатором в момент его инициализации, вы можете создать класс сериализатора следующим образом:
Это позволит вам сделать следующее:
Настройка полей по умолчанию
REST framework 2 предоставил API, позволяющий разработчикам переопределять, как класс ModelSerializer
будет автоматически генерировать набор полей по умолчанию.
Этот API включал методы .get_field()
, .get_pk_field()
и другие.
Поскольку сериализаторы были кардинально переработаны в версии 3.0, этот API больше не существует. Вы все еще можете изменять создаваемые поля, но вам придется обратиться к исходному коду, и имейте в виду, что если изменения, которые вы делаете, направлены против частных частей API, то они могут быть изменены.
Пакеты сторонних производителей
Также доступны следующие пакеты сторонних производителей.
Django REST marshmallow
Пакет django-rest-marshmallow предоставляет альтернативную реализацию сериализаторов, используя библиотеку python marshmallow. Он предоставляет тот же API, что и сериализаторы DRF, и может быть использован в качестве замены в некоторых случаях.
Serpy
Пакет serpy - это альтернативная реализация сериализаторов, созданная для скорости. Serpy сериализует сложные типы данных в простые нативные типы. Родные типы могут быть легко преобразованы в JSON или любой другой необходимый формат.
MongoengineModelSerializer
Пакет django-rest-framework-mongoengine предоставляет класс сериализатора MongoEngineModelSerializer
, который поддерживает использование MongoDB в качестве уровня хранения данных для DRF.
GeoFeatureModelSerializer
Пакет django-rest-framework-gis предоставляет класс сериализатора GeoFeatureModelSerializer
, который поддерживает GeoJSON как для операций чтения, так и для записи.
HStoreSerializer
Пакет django-rest-framework-hstore предоставляет HStoreSerializer
для поддержки поля модели django-hstore DictionaryField
и его функции chema-mode
.
Dynamic REST
Пакет dynamic-rest расширяет интерфейсы ModelSerializer и ModelViewSet, добавляя параметры запроса API для фильтрации, сортировки, включения/исключения всех полей и отношений, определенных вашими сериализаторами.
Dynamic Fields Mixin
Пакет drf-dynamic-fields предоставляет миксин для динамического ограничения полей для сериализатора подмножеством, заданным параметром URL.
DRF FlexFields
Пакет drf-flex-fields расширяет ModelSerializer и ModelViewSet для обеспечения широко используемой функциональности для динамической установки полей и расширения примитивных полей во вложенные модели, как из параметров URL, так и из определений класса вашего сериализатора.
Serializer Extensions
Пакет django-rest-framework-serializer-extensions предоставляет набор инструментов для DRY up ваших сериализаторов, позволяя определять поля на основе каждого представления/запроса. Поля могут быть внесены в белый или черный список, а дочерние сериализаторы могут быть расширены по желанию.
HTML JSON Forms
Пакет html-json-forms предоставляет алгоритм и сериализатор для обработки <form>
в соответствии с (неактивной) спецификацией HTML JSON Form. Сериализатор облегчает обработку произвольно вложенных структур JSON в HTML. Например, <input name="items[0][id]" value="5">
будет интерпретирован как {"items": [{"id": "5"}]}
.
DRF-Base64
DRF-Base64 предоставляет набор сериализаторов полей и моделей, который обрабатывает загрузку файлов в base64-кодировке.
QueryFields
djangorestframework-queryfields позволяет клиентам API указать, какие поля будут отправлены в ответе с помощью параметров запроса включения/исключения.
DRF Writable Nested
Пакет drf-writable-nested предоставляет записываемый сериализатор вложенных моделей, который позволяет создавать/обновлять модели с вложенными связанными данными.
DRF Encrypt Content
Пакет drf-encrypt-content помогает вам шифровать данные, сериализованные через ModelSerializer
. Он также содержит некоторые вспомогательные функции. Это поможет вам зашифровать ваши данные.
Last updated