Как работает сериализатор в Django REST Framework
Что проверяют
Понимаете ли вы, что сериализатор в DRF работает в обе стороны: превращает объекты в примитивы для ответа и проверяет входные данные перед сохранением. Следом обычно спрашивают про порядок валидации и про вложенные сериализаторы.
Как отвечать
Базовых класса два: serializers.Serializer, где поля и методы create()/update() описываются вручную, и ModelSerializer, который строит поля и валидаторы по модели через class Meta с model и fields.
Работа идёт в трёх режимах:
- сериализация:
MySerializer(instance).dataвызываетto_representation()у каждого поля. Для списка передаютmany=True, тогда создаётсяListSerializer; - десериализация:
MySerializer(data=request.data), затемis_valid(). Оно запускаетto_internal_value()и валидаторы полей, методыvalidate_<поле>(), потом общийvalidate(self, attrs). Результат лежит вvalidated_data, ошибки вerrors; - сохранение:
save()вызываетcreate(), если сериализатор создан без объекта, иupdate(), если переданinstance. Для PATCH добавляютpartial=True.
Полезные детали: read_only=True и write_only=True у полей, source для переименования, SerializerMethodField для вычисляемых значений, context для доступа к request. В представлениях удобно писать is_valid(raise_exception=True): DRF сам вернёт 400 с текстом ошибок.
Где спотыкаются
Путают методы: называют несуществующий serialize() или вызывают create() напрямую вместо save(). Обращение к .data или save() до is_valid() при переданных data падает с AssertionError.
Ждут, что вложенный сериализатор сам сохранит связанные объекты. ModelSerializer по умолчанию не умеет записывать вложенные данные, create() и update() для этого переопределяют вручную.
Не думают о запросах к базе. Вложенный сериализатор на списке из сотни объектов даёт сотню дополнительных запросов, если в queryset нет select_related или prefetch_related.