3

We have an APIView (FooView) that can be accessed directly through a URL.

We have another APIView APIKeyImportView that will reuse FooView depending of file name (it is done this way for compatibility with an API).

However when request.FILES is accessed from APIKeyImportView to look at the file names, request.FILES becomes empty in FooView.

It appears that accessing request.FILES will makes it un-useable by the nested view.

Is there a way around this?

  class FooView(APIView):
      permission_classes = (permissions.IsAuthenticated,)

      def post(self, request, vendor):
          file = request.FILES.get('file')
          if not file:
              return Response(status=status.HTTP_400_BAD_REQUEST)
          return Response()


  class APIKeyImportView(APIView):
      permission_classes = (permissions.IsAuthenticated,)
      authentication_classes = (ApiKeyAuthentication,)

      def post(self, request):
          file = request.FILES.get('file')
          if not file:
              return Response(status=status.HTTP_400_BAD_REQUEST)
          name = file.name

          if name.startswith('FOO'):
              return FooView.as_view()(request=request)
          else:
              return Response(status=status.HTTP_400_BAD_REQUEST)

Removing the validation on request.Files in APIKeyImportView will make it accessible in FooView but it kinds of miss the point.

Inspecting request in PyCharm will also make it un-useable in FooView since the debugger will call the properties.

  class APIKeyImportView(APIView):
      permission_classes = (permissions.IsAuthenticated,)
      authentication_classes = (ApiKeyAuthentication,)

      def post(self, request):
          return FooView.as_view()(request=request)

These solutions are not working:

django modifying the request object

Tested on the following versions:

  • Django 1.9.5
  • django-rest-framework 3.3.3
  • Python 3.4.2
GabLeRoux
  • 16,715
  • 16
  • 63
  • 81
jrobichaud
  • 1,272
  • 1
  • 11
  • 23

1 Answers1

2

A workaround I found was to pass request.FILES but I am not sure if it has side effects

  class FooView(APIView):
      permission_classes = (permissions.IsAuthenticated,)

      _files = None

      @property
      def request_files(self):
          if self._files:
              return self._files
          return self.request.FILES

      def post(self, request, vendor):
          file = self.request_files.get('file')
          if not file:
              return Response(status=status.HTTP_400_BAD_REQUEST)
          return Response()


  class APIKeyImportView(APIView):
      permission_classes = (permissions.IsAuthenticated,)
      authentication_classes = (ApiKeyAuthentication,)

      def post(self, request):
          file = request.FILES.get('file')
          if not file:
              return Response(status=status.HTTP_400_BAD_REQUEST)
          name = file.name

          if name.startswith('FOO'):
              # Passing FILES here
              return FooView.as_view(_files=request.FILES)(request=request)
          else:
              return Response(status=status.HTTP_400_BAD_REQUEST)
jrobichaud
  • 1,272
  • 1
  • 11
  • 23