3

I am attempting to override the update method for a put request in django rest framework. Instead of returning just the updated object. I want it to return the entire queryset including the updated object. For the use case I am working on, its just easier.

Starting from the top.

I am using Django Rest Frameworks Generics.

class SearchCityDetail(RetrieveUpdateDestroyAPIView):
    queryset = SearchCity.objects.all()
    serializer_class = SearchCitySerializer

I override the classes PUT method and inherent from my custom mixin.

class SearchCityDetail(RetrieveUpdateDestroyAPIView, UpdateReturnAll):
queryset = SearchCity.objects.all()
serializer_class = SearchCitySerializer

def put(self, request, *args, **kwargs):
    return self.updatereturnall(self,request, *args, **kwargs)

the custom mixin looks like this (my custom added code which differs from the normal update code had the commment #Custom Code above it:

    from rest_framework import status
    from rest_framework.response import Response
    from rest_framework.settings import api_settings
    from rest_framework.mixins import UpdateModelMixin
    """
       Update a model instance and return all.
   """
#Custom Code
class UpdateReturnAll(UpdateModelMixin):

    #custom name normally just update
    def updatereturnall(self, request,  model, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        #all objects and all serializer is custom code 
        allobjects = self.get_queryset(self)
        allserializer = self.get_serializer(allobjects, many=True)

        return Response(allserializer.data)


    def perform_update(self, serializer):
        serializer.save()


    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)

The self.get_queryset and the self.get_serializer are functions defined in the GenericAPIView which RetrieveUpdateDestroyAPIView inherents from. And since I am inheriting the UpdateReturnAll into the SearchCityDetail class the two methods should be available to the UpdateReturnALL

that is my understanding.

I am currently getting an error and status code 500

the error being: AttributeError: 'SearchCityDetail' object has no attribute 'data'

what am I doing wrong?

1 Answers1

1

It should be:

class SearchCityDetail(RetrieveUpdateDestroyAPIView, UpdateReturnAll):
    queryset = SearchCity.objects.all()
    serializer_class = SearchCitySerializer

    def put(self, request, *args, **kwargs):
        return self.updatereturnall(request, *args, **kwargs)

Instead of return self.updatereturnall(self,request, *args, **kwargs).

Don't need to pass self argument explicit when call self.updatereturnall method, Python do it for you.

neverwalkaloner
  • 46,181
  • 7
  • 92
  • 100
  • well done thank you very much. Why does python do it for us? What is the cause? – amazing carrot soup Mar 02 '18 at 17:03
  • @amazingcarrotsoup you are welcome! Well, in Python there are bound and unbound methods. Method in your code is bound to specific instance, so you cannot pass any other instance as self argument. Check this question for details https://stackoverflow.com/questions/114214/class-method-differences-in-python-bound-unbound-and-static – neverwalkaloner Mar 02 '18 at 17:36
  • Does it also work for PATCH requests as well? – Manish Shah Mar 23 '21 at 20:17