DjangoRestFramework アップロード ファイル「CSRF 検証に失敗しました」
-
23-12-2019 - |
質問
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',
)
}
解決
1) 元のコードでは、ファイル名パラメーターがビューに表示されることを期待していましたが、urls.py 内の URL からそれを解析していませんでした。次のようになっているはずです。
url(r'^uploads/(?P<filename>[\w.]{0,256})/$', views.UploadsView.as_view()),
2) APIView もビューとして提供していませんでした。上記でお気づきかと思いますが、私は特に .as_view() メソッドを呼び出しています。
上記を修正し、PUT の代わりに POST を実装すると、コードは期待どおりに機能します。これが私の現在の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)
他のヒント
django REST FrameworkのDocumation > SessionAuthenticationを使用している場合は、POST、PUT、PATCH、DELETE操作に対して有効なCSRFトークンを含める必要があります。
Ajax要求をするためには、 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)
. 所属していません StackOverflow