从Django中的表单发送DELETE请求

我试图从Django中的表单发送DELETE请求,从jQuery获取帮助,参考下面的链接;

https://baxeico.wordpress.com/2014/06/25/put-and-delete-http-requests-with-django-and-jquery/

我所拥有的是以下脚本;

  $(document).ready(function(){ $.ajax({ id : 'delete', headers : {'X_METHODOVERRIDE': 'DELETE'} }); });  

(我打算)采取以下forms行事;

 
{% csrf_token %}

以及中间件;

 from django.http import QueryDict class HttpPostTunnelingMiddleware(object): def process_request(self, request): if request.META.has_key('HTTP_X_METHODOVERRIDE'): http_method = request.META['HTTP_X_METHODOVERRIDE'] if http_method.lower() == 'put': request.method = 'PUT' request.META['REQUEST_METHOD'] = 'PUT' request.PUT = QueryDict(request.body) if http_method.lower() == 'delete': request.method = 'DELETE' request.META['REQUEST_METHOD'] = 'DELETE' request.DELETE = QueryDict(request.body) return None 

我把它添加到我的settings.py中的MIDDLEWARE_CLASSES列表中;

 MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'stationrunner.middleware.HttpPostTunnelingMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ) 

这是第三个条目,在CsrfViewMiddleware考虑@Daniel Roseman的话之前。

最后在我的基于类的视图中我有删除方法删除相应的对象;

 class StationHome(View): . . . def post(self,request, pk): station = Station.objects.get(pk=pk) form = StationForm(request.POST, instance=station) if form.is_valid(): form.save() return HttpResponseRedirect(reverse("home_station", kwargs={'pk':pk}, ) ) else: return HttpResponse("Form Invalid!") def delete(self, request, pk): Station.objects.get(pk=pk).delete() return HttpResponseRedirect( reverse("list_create_station") ) . . 

我希望中间件和脚本向视图发送DELETE请求,但事情并没有发生。 POST方法本身正在发送。 Django找到了一个无效的表格并给我回复; “表格无效!” ( else: return HttpResponse("Form Invalid!"

更新

我已经更新了脚本看起来像;

  $(document).ready(function(){ $('#delete').submit.function(e){ e.preventDefault(); var station_id = {{ station.id }} $.ajax({ type: 'POST', url: '/station/' + station_id, headers: {'X_METHODOVERRIDE': 'DELETE'} }); }); });  

我将对象作为station传递给模板,我在脚本中使用了Django模板语言( var station_id = {{ station.id }} ),灵感来自https://stackoverflow.com/a/6008968/4672736

结果是一样的 :/

更新

调试js发现浏览器没有找到jQuery文件。 现在正确配置了静态文件,并且在jquery.cookie.js的帮助下设置了csrf保护我在我的模板中有以下代码;

    $(document).ready(function(){ var csrftoken = $.cookie('csrftoken'); function csrfSafeMethod(method) { // these HTTP methods don't require CSRF protection return(/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function(xhr, settings) { if(!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } }); $('#delete').submit(function(e){ e.preventDefault(); $.ajax({ type: 'POST', url: '{% url 'home_station' station.id %}', headers: {'X_METHODOVERRIDE': 'DELETE'} }); }); });  

现在我在前端没有错误但是还没有成功。 提交表单得到200响应,而不是302

这是预期的AJAX请求吗?

似乎请求尚未作为删除请求传递给视图。

我尝试将success: function(){alert('Object deleted!')}$.ajax并弹出警报。

更新

最后一个障碍是我必须在传递的自定义标头中使用短划线而不是下划线。 我将headers: { 'X_METHODOVERRIDE': 'DELETE' }更改为headers: { 'X-METHODOVERRIDE': 'DELETE' } 。 这些字母也不必用大写字母传递。 无论如何,Django会将它们转换为大写字母。 因此x-methodoverridex-MeThODoveRrIDE也很好。 我不知道为什么破灭而不是下划线。 我想通了,因为传递的其他标题是带有破折号而不是下划线。

早些时候,中间件没有找到密钥HTTP_X_METHODOVERRIDE 。 现在它确实和我的视图获取删除请求:)

问题出在你的javascript代码上。 您将表单作为常规POST请求提交,而不是使用$ .ajax javascript代码。

您应该在单独的脚本标记中包含jquery,如下所示:

  

然后在另一个脚本标记中放置代码:

  

在这里,我假设您在表单字段中具有要删除的对象的ID,如下所示:

 
{% csrf_token %}

请注意Ajax调用上的Django CSRF保护,你应该写一些javascript来在请求中设置你的CSRF cookie值,如Django文档中所述 。

将HttpResponseRedirect返回到Ajax调用也没有多大意义,因为浏览器不会像常规POST请求那样重定向到该页面。

在挖掘像这样的更复杂的例子之前,我建议更多地研究jquery和Ajax请求是如何工作的。 ;)

这可能是中间件的排序。 收到请求后,将按照在设置中指定的顺序处理中间件。 在您的情况下,这意味着首先运行CSRF中间件,看到请求是没有CSRF令牌的POST,并引发错误。

尝试在CsrfViewMiddleware之前移动您的HttpPostTunnelingMiddleware。