【问题标题】:DjangoRestFramework upload file 'CSRF Verification Failed'DjangoRestFramework 上传文件“CSRF 验证失败”
【发布时间】:2014-03-31 09:44:26
【问题描述】:

我正在使用 DjangoRestFramework 来制作 API。目前我有 OAuth2 身份验证工作,这意味着我可以生成一个有效的访问令牌来使用 API。

如何上传用户文件?我需要上传一个文件并将其与上传它的用户相关联。

我目前正在尝试这样做

api/views.py:

class FileUploadView(APIView):
    parser_classes = (FileUploadParser,)

    def put(self, request, filename, format=None):
        file_obj = request.FILES['file']
        # do stuff
        return Response(status=204)

api/urls.py 包含这一行:

url(r'^files/', 'api.views.FileUploadView'),

但是当我尝试上传文件时,我收到一条错误消息:

'CSRF verification failed. Request aborted'
'Reason given for failure: CSRF cookie not set'

当我尝试这个 curl 命令时:

curl -XPUT http://localhost:8000/files/ -H 'Authorization: Bearer some_access_token' -F filedata=@localfile.txt

这是我的 REST_FRAMEWORK 默认值:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.OAuth2Authentication',
    )
}

【问题讨论】:

标签: python django oauth oauth-2.0 django-rest-framework


【解决方案1】:

1) 在我的原始代码中,我期待一个文件名参数进入我的视图,但我没有从 urls.py 中的 url 解析它。它应该看起来像这样:

url(r'^uploads/(?P<filename>[\w.]{0,256})/$', views.UploadsView.as_view()),

2) 我也没有提供 APIView 作为视图。如果您注意到上面我专门调用了 .as_view() 方法。

通过上述修复并实现 POST 而不是 PUT,我的代码可以按预期工作。这是我当前的 APIView:

class UploadsView(APIView):

    parser_classes = (FileUploadParser,)
    permission_classes = (permissions.IsAuthenticated,)

    def post(self, request, format=None):
        file_obj = request.FILES['file']
        print("FILE OBJ: ", file_obj)
        return Response(status=201)

【讨论】:

  • 谢谢。我遇到了同样的问题,忘了做.as_view()
  • 我想指出,你不需要使用scrf_excempt 或覆盖dispatcher 时使用APIView...
【解决方案2】:

根据Django REST Framework Documentation,“如果您使用 SessionAuthentication,则需要为任何 POST、PUT、PATCH 或 DELETE 操作包含有效的 CSRF 令牌。

为了发出 AJAX 请求,您需要在 HTTP 标头中包含 CSRF 令牌,如 Django documentation 中所述。"

或者,您可以尝试制作此视图CSRF Exempt

from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt

class FileUploadView(APIView):
    parser_classes = (FileUploadParser,)

    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super(FileUploadView, self).dispatch(request, *args, **kwargs)

    def put(self, request, filename, format=None):
        file_obj = request.FILES['file']
        # do stuff
        return Response(status=204)

【讨论】:

  • dispatch()方法内部已经是csrf_exempt了,不需要自己做。我也默认使用 OAuth2Authentication,而不是 SessionAuthentication。我已经发布了我的解决方案。
猜你喜欢
  • 2014-01-09
  • 2015-08-26
  • 1970-01-01
  • 1970-01-01
  • 2012-09-08
  • 2015-06-02
  • 1970-01-01
相关资源
最近更新 更多