AttributeError 'UserViewset' object has no attribute 'action'

Issue

I’ve been using the Django rest framework, and I’m trying to customize the get_parsers method in my UserViewset, I looked at the docs and found a similar use case with permission classes in docs, and I tried to customize the get_parsers like this

class UserViewset(viewsets.ModelViewSet):
serializer_class = UserSerializer

# Redefine get_parsers, so that only the update methods have form-data media type
def get_parsers(self):
    if self.action == 'update' or self.action == 'partial_update':
        parser_classes = [FormParser, MultiPartParser]
    else:
        parser_classes = [JSONParser]
    return [parser() for parser in parser_classes]

but I keep getting the error: AttributeError at /api/auth/users/: 'UserViewset' object has no attribute 'action'
I tried the use case found in the docs and it worked perfectly.
What am I doing wrong here ?

Solution

So, thanks to fb.com/laidani.basset @bdbd and @willem-van-onsem and u/vikingvynotking, I’ve been able to fix it with 2 different solutions:

  • The first is to override initialize_request like this, the idea is to set the request parsers to the instance of which parser you want; the drop back is when you’re using swagger or any API doc, it’ll not differentiate between the method parsers and it’ll be just one parser, in my case it’s JSONParser:

     def initialize_request(self, request, *args, **kwargs):
    
         request = super().initialize_request(request, *args, **kwargs)
         print(request.method)
         if request.method in ['PUT', 'PATCH']:
             request.parsers = [FormParser(), MultiPartParser()]
         else:
             request.parsers = [JSONParser()]
    
         self.action = self.action_map.get(request.method.lower())
         return request
    
  • The second solution is to override initialize_request so that the self.action is called before calling the request, and then use the get_parsers method as you like, in this case, the swagger will differentiate between the parsers of each method:

     def initialize_request(self, request, *args, **kwargs):
         self.action = self.action_map.get(request.method.lower())
         return super().initialize_request(request, *args, **kwargs)
    

Answered By – Sohaib Smahi

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published