DjangoRestFramework上传文件'CSRF验证失败'

时间:2014-02-27 18:36:10

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

我正在使用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',
    )
}

2 个答案:

答案 0 :(得分:3)

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)

答案 1 :(得分:0)

根据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)