2014-02-27 79 views
1

我正在使用DjangoRestFramework來製作API。目前我有OAuth2認證工作,這意味着我可以生成一個有效的訪問令牌來使用API​​。DjangoRestFramework上傳文件'CSRF驗證失敗'

如何上傳用戶文件?我需要上傳文件並將其與上傳文件的用戶關聯起來。

我目前正在做這樣

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 [email protected] 

這裏是我的REST_FRAMEWORK默認:

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

見https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/#exceptions – user1168095

回答

2

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) 
0

Django REST Framework Documentation,「如果你使用SessionAuthentication您必須包括有效的CSRF令牌進行任何POST,PUT,PATCH或DELETE操作。

爲了使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) 
+0

調度()方法是已經在內部csrf_exempt,沒有必要做它自己。我也默認使用OAuth2Authentication,而不是SessionAuthentication。我發佈了我的解決方案。 – arnm