with queryset instalar framework espaƱol python json django serialization django-rest-framework

python - queryset - django-rest-framework 3.0 crear o actualizar en serializador anidado



django rest framework with django 2 (2)

Con django-rest-framework 3.0 y tener estos modelos simples:

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)

Y dada esta solicitud JSON:

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

¿Cómo puedo escribir un serializador anidado para procesar este JSON y para cada page del book dado crear una nueva página o actualizarla si existe?

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

Sé que instanciar el serializador con una instance actualizará el actual, pero ¿cómo debo usarlo dentro del método de create del serializador anidado?


En primer lugar, ¿desea apoyar la creación de nuevas instancias de libros o solo actualizar las existentes?

Si alguna vez quisieras crear nuevas instancias de libros, podrías hacer algo como esto ...

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

Tenga en cuenta que no he incluido el book_id aquí. Cuando creamos instancias de libros, no incluiremos una identificación de libro. Cuando estamos actualizando instancias de libros, normalmente incluiremos la identificación del libro como parte de la URL, en lugar de en los datos de la solicitud.

Si desea admitir tanto la creación como la actualización de instancias de libros, debe pensar cómo desea manejar las páginas que no están incluidas en la solicitud, pero que actualmente están asociadas con la instancia de libro.

Puede optar por ignorar silenciosamente esas páginas y dejarlas como están, es posible que desee generar un error de validación o que desee eliminarlas.

Supongamos que desea eliminar cualquier página no incluida en la solicitud.

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

También es posible que desee admitir solo actualizaciones de libros y no admitir la creación, en cuyo caso, solo incluya el método update() .

También hay varias formas de reducir el número de consultas, por ejemplo. usando la creación / eliminación masiva, pero lo anterior haría el trabajo de una manera bastante sencilla.

Como puede ver, hay sutilezas en los tipos de comportamiento que puede desear cuando se trata de datos anidados, por lo tanto, piense detenidamente sobre exactamente qué comportamiento espera en varios casos.

También tenga en cuenta que he estado usando Serializer en el ejemplo anterior en lugar de ModelSerializer . En este caso, es más simple incluir explícitamente todos los campos en la clase de serializador, en lugar de depender del conjunto automático de campos que ModelSerializer genera de forma predeterminada.


Simplemente puede usar drf-writable-nested . Automáticamente hace que sus serializadores anidados sean editables y actualizables.

en ti serializers.py :

from drf_writable_nested import WritableNestedModelSerializer class RequestSerializer(WritableNestedModelSerializer): book_id = serializers.IntegerField() page = PageSerializer(many=True) class PageSerializer(serializers.ModelSerializer): class Meta: model = Page

¡Y eso es!

Además, la biblioteca admite el uso de solo una de las lógicas de create y update si no necesita ambas.