我正在将我的项目移植到 Django Rest Framework 来为我的项目制作一个合适的 REST Api,我认为这对设计 API 并使其健壮有很大帮助,但我遇到了一个问题:
我有一个入门模型和关联的ListCreateAPIView
and RetrieveUpdateDestroyAPIView
意见。
我可以通过 ajax 请求成功在列表中发布一个新的条目实例并提供csrfmiddlewaretoken
就像我在常规 Django 视图中所做的那样。
POST entries/
现在我尝试使用相同的方法将补丁应用到现有实例csrfmiddlewaretoken
像这样:
PATCH entries/3
那么响应状态码是403 FORBIDDEN
存在错误CSRF Failed: CSRF token missing or incorrect
虽然我在 firebux 中检查过csrfmiddlewaretoken
在请求数据中。
我不知道出了什么问题,也无法找出代码中的请求被拒绝的位置。
Note:我可以使用 Django Rest Framework 可浏览 api 修补该对象。
我希望有人能帮帮忙。
谢谢。
奥利维尔
EDIT
我正在深入研究代码以查看 PATCH 请求被拒绝的位置,我发现django.middleware.csrt.py
下列:
if csrf_token is None: #<--- csrf_token is defined
# No CSRF cookie. For POST requests, we insist on a CSRF cookie,
# and in this way we can avoid all CSRF attacks, including login
# CSRF.
return self._reject(request, REASON_NO_CSRF_COOKIE)
# Check non-cookie token for match.
request_csrf_token = ""
if request.method == "POST": #<--- This fails but request_csrf_token is in request.DATA
request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
if request_csrf_token == "":
# Fall back to X-CSRFToken, to make things easier for AJAX,
# and possible for PUT/DELETE.
request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
第二个测试失败,因为它不是 POST 请求,但所需的信息位于 request.DATA 中。
所以看来django并不热衷于接受PATCH请求。
您认为解决这个问题的最佳方法是什么?
您是否建议使用不同的身份验证系统(Django-rest-framework 文档中有一些)?
EDIT2
我找到了一个解决方案:
我观察到可浏览的 api 实际上正在发送一个 POST 请求,但带有参数 _method="PATCH",所以我对我的 ajax 请求做了同样的事情,并且工作正常。
不知道这样的做法是否正确,欢迎大家反馈和意见!
EDIT3
因此,经过更多阅读后,我发现(我已经有点知道了..)由于某些浏览器不支持 PUT、PATCH、DELETE 等请求,因此解决方法是使用 X-HTTP-Method-Override 发送 post 请求在标题中。
因此,我认为最好的方法是执行以下操作:
$.ajax({
headers: {
'X-HTTP-Method-Override': 'PATCH'
},
type : "POST",
...
});