django-rest-framework 3.0 создавать или обновлять в вложенном сериализаторе

С django-rest-framework 3.0 и с этими простыми моделями:

class Book(models.Model): title = models.CharField(max_length=50) class Page(models.Model): book = models.ForeignKey(Books, related_name='related_book') text = models.CharField(max_length=500) 

И учитывая этот запрос JSON:

 { "book_id":1, "pages":[ { "page_id":2, "text":"loremipsum" }, { "page_id":4, "text":"loremipsum" } ] } 

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

 class RequestSerializer(serializers.Serializer): book_id = serializers.IntegerField() page = PageSerializer(many=True) class PageSerializer(serializers.ModelSerializer): class Meta: model = Page 

Я знаю, что создание экземпляра сериализатора с instance будет обновлять текущий, но как его использовать внутри метода создания вложенного сериализатора?

  • Редактирование объекта сериализатора django-rest-framework перед сохранением
  • Поле SerializerClass в Сериализаторе сохранить с первичного ключа
  • datetime.date (2014, 4, 25) не является JSON-сериализуемым в Django
  • Получить текущего пользователя в сериализаторе модели
  • Динамически исключать или включать поле в сериализатор рамки Django REST
  • Как получается, что сериализация json намного быстрее, чем сериализация yaml в Python?
  • django-rest-framework: как мне сериализовать поле, которое уже содержит JSON?
  • Почему json-сериализация объектов datetime в python не работает из коробки для объектов datetime
  • One Solution collect form web for “django-rest-framework 3.0 создавать или обновлять в вложенном сериализаторе”

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

    Если вы только хотели создать новые экземпляры книг, вы могли бы сделать что-то вроде этого …

     class PageSerializer(serializers.Serializer): text = serializers.CharField(max_length=500) class BookSerializer(serializers.Serializer): page = PageSerializer(many=True) title = serializers.CharField(max_length=50) def create(self, validated_data): # Create the book instance book = Book.objects.create(title=validated_data['title']) # Create or update each page instance for item in validated_data['pages']: page = Page(id=item['page_id'], text=item['text'], book=book) page.save() return book 

    Обратите внимание: я не включил здесь book_id . Когда мы создаем экземпляры книг, мы не будем включать идентификатор книги. Когда мы обновляем экземпляры книг, мы обычно включаем идентификатор книги как часть URL-адреса, а не в данные запроса.

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

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

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

     def create(self, validated_data): # As before. ... def update(self, instance, validated_data): # Update the book instance instance.title = validated_data['title'] instance.save() # Delete any pages not included in the request page_ids = [item['page_id'] for item in validated_data['pages']] for page in instance.books: if page.id not in page_ids: page.delete() # Create or update page instances that are in the request for item in validated_data['pages']: page = Page(id=item['page_id'], text=item['text'], book=instance) page.save() return instance 

    Также возможно, что вам может потребоваться только поддержка обновлений книг, а не поддержка создания, и в этом случае включить метод update() .

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

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

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

    Interesting Posts

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

    SymPy / SciPy: решение системы обыкновенных дифференциальных уравнений с различными переменными

    Как запускать файлы яиц Python напрямую, не устанавливая их?

    ImportError: Ошибка загрузки DLL:% 1 не является допустимым приложением Win32 для Python Matplotlib

    Python xlwt – доступ к существующему содержимому ячейки, автоматическая настройка ширины столбца

    Функция расстояния Django не возвращает объект расстояния

    Python beautifulsoup перебирает таблицу

    Чтение из CSV: разделитель должен быть строкой, а не юникодом

    Scrapy Installation Fails with error 'can not open include:' openssl / aes.h '

    Как сохранить имена столбцов, начинающиеся с минуса при использовании numpy.genfromtxt?

    Вход в графический интерфейс на основе текста Python (TUI)

    Подавлять вызовы на печать (python)

    Быстрый метод для поиска строки в большом текстовом файле с помощью python

    Какова самая быстрая система шаблонов для Python?

    ImportError: нет модуля с именем six

    Python - лучший язык программирования в мире.