2
votes

I'm writing a serializer to provide multiple partial updates to a django model. I'm following the example implementation that appears in the DRF api guide, reproduced below and linked here: https://www.django-rest-framework.org/api-guide/serializers/#customizing-multiple-update.

The following was retrieved from django-rest-framework documentation:

serializer.py

class BookListSerializer(serializers.ListSerializer):
    def update(self, instance, validated_data):
        # Maps for id->instance and id->data item.
        book_mapping = {book.id: book for book in instance}
        data_mapping = {item['id']: item for item in validated_data}

        # Perform creations and updates.
        ret = []
        for book_id, data in data_mapping.items():
            book = book_mapping.get(book_id, None)
            if book is None:
                ret.append(self.child.create(data))
            else:
                ret.append(self.child.update(book, data))

        # Perform deletions.
        for book_id, book in book_mapping.items():
            if book_id not in data_mapping:
                book.delete()

        return ret

class BookSerializer(serializers.Serializer):
    # We need to identify elements in the list using their primary key,
    # so use a writable field here, rather than the default which would be read-only.
    id = serializers.IntegerField()
    ...

    class Meta:
        list_serializer_class = BookListSerializer

In my code I'm getting a NotImplementedError('update() must be implemented.') in my views.py when .save() is called on the serializer that is returned.

My understanding is that the ListsSerializer overrides the .update(), so could anyone help explain why I'm getting the NotImpletmentedError?

views.py

elif request.method == 'PATCH':
        data = JSONParser().parse(request)
        books = Book.objects.all()
        # both partial and many set to True
        serializer = BookSerializer(books, data=data, partial=True, many=True)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data)
        return JsonResponse(serializer.errors, status=400)
1
Hi, is the LoadingPatchSerializer the one raising the error? Can you show it's implementation, please?luistm
@luistm, sorry that should be the BookSerializer. I've edited it. The error is coming from serializer.save().NickF
You need to override the method there on BookSerializerluistm
@luistm, ah! that worked. Thanks for your help.NickF
This solution did not work for me. I found another way to make it work, see my answer here: stackoverflow.com/a/59756993/7392069Greg Holst

1 Answers

2
votes

With the help of @luistm, I managed to solve this. Continuing with the DRF example above my implementation of the update() override in the bookSerializer class was as below.

serializer.py

class BookSerializer(serializers.Serializer):
    # We need to identify elements in the list using their primary key,
    # so use a writable field here, rather than the default which would be read-only.
    id = serializers.IntegerField()
    ...

    class Meta:
        list_serializer_class = BookListSerializer

    def update(self, instance, validated_data):
         """update the page number of the book and save"""
         instance.page = validated_data.get('page', instance.page)
         instance.save()
         return instance