如果调用request.FILES属性,则嵌套APIView中断请求

时间:2017-08-24 14:16:32

标签: django debugging request django-rest-framework

我们有一个APIViewFooView)可以通过网址直接访问。

我们还有另一个APIView APIKeyImportView将根据文件名重用FooView(这样做是为了与API兼容)。

但是,当从request.FILES访问APIKeyImportView以查看文件名时,request.FILES中的FooView将变为空。

访问request.FILES似乎会使嵌套视图无法使用。

有解决方法吗?

  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)

删除request.FilesAPIKeyImportView上的验证将使其在FooView中可访问,但它有点遗漏这一点。

检查PyCharm中的request也会使其在FooView中无法使用,因为调试器会调用属性。

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

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

这些解决方案无效:

django modifying the request object

测试了以下版本:

  • Django 1.9.5
  • django-rest-framework 3.3.3
  • Python 3.4.2

1 个答案:

答案 0 :(得分:2)

我找到的解决方法是通过request.FILES,但我不确定它是否有副作用

  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)