从Django中的表单发送DELETE请求 [英] Sending a DELETE request from a form in Django

查看:196
本文介绍了从Django中的表单发送DELETE请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我正在尝试从Django中的表单发送DELETE请求.wordpress.com / 2014/06/25 / put-and-delete-http-requests-with-django-and-jquery /rel =nofollow noreferrer> https://baxeico.wordpress.com/2014/06 / 25 / put-and-delete-http-requests-with-django-and-jquery /



我有以下脚本; p>

 < script src =jquery-1.11.3.js>< / script> 

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

(我打算拥有)采用以下表单:

 < form method =postid =deletename =deleteaction => 
{%csrf_token%}
< input type =submitvalue =删除/>
< / form>

以下中间件;

  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']
如果http_method.lower()=='put':
request.method ='PUT'
request.META ['REQUEST_METHOD'] ='PUT'
request.PUT = QueryDict(request.body)
如果http_method.lower()=='delete':
request.method ='DELETE'
request.META ['REQUEST_METHOD'] ='DELETE'
request.DELETE = QueryDict(request.body)
return无

我已将其添加到我的settings.py中的MIDDLEWARE_CLASSES列表中;

  MIDD LEWARE_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。 message.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)
如果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!



如果你在这里找到愚蠢的东西。我是Django的新手,只在今天才认识了jQuery。



更新



我已将脚本更新为

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

我将对象传递给模板作为我已经使用脚本中的Django模板语言( var station_id = {{station.id}} ),从 https://stackoverflow.com/a/6008968/4672736



结果是一样的:/



更新



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

 < script src ={%staticstationrunner / jquery-1.11.3.js%}>< / script> 
< script src ={%staticstationrunner / jquery.cookie.js%}>< / script>

< script>
$(document).ready(function(){
var csrftoken = $ .cookie('csrftoken');
函数csrfSafeMethod(method){
//这些HTTP方法不需要CSRF保护
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%}',
标题:{'X_METHODOVERRIDE':'DELETE'}
});
});
});
< / script>

现在我的前端没有错误,但成功还没有满足。表单的提交给我一个 200 回应,而不是 302



这是否需要AJAX请求?



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



我尝试添加 success:function(){alert('Object deleted!')} to $。 ajax ,并弹出警报。



更新



最后一个障碍是我不得不在自定义标题传递而不是下划线。我更改了标题:{'X_METHODOVERRIDE':'DELETE'} 标题:{'X-METHODOVERRIDE':'DELETE'} 。这些信件也不必大写。无论如何将Django转换成首都。所以 x-methodoverride x-MeThODoveRrIDE 我不知道为什么破折号,而不是突出显示。我想到,其他标题通过都带有破折号而不是下划线。



早期的中间件没有找到密钥 HTTP_X_METHODOVERRIDE 。现在它和我的看法得到一个删除请求:)。感谢@baxeico的所有帮助。

解决方案

问题在于您的JavaScript代码。您正在提交表单作为常规POST请求,而不是使用$ .ajax JavaScript代码。



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

 < script src =http://code.jquery.com/jquery-1.11.3.min.js >< /脚本> 

然后在另一个脚本标签中,输入代码:

 < script> 
$('#delete')。submit(function(e){
//不要将表单作为常规POST请求提交
e.preventDefault();
var object_to_delete_id = $('#object_to_delete_id')。val();
$ .ajax({
type:'POST',
url:'/ your-view-url /'+ object_to_delete_id ,
success:function(){
alert('Object deleted!')
},
标题:{'X_METHODOVERRIDE':'DELETE'}
}) ;
});
< script>

这里我假设你有一个表单字段中要删除的对象的ID像这样:

 < form method =postid =deletename =deleteaction => ; 
{%csrf_token%}
< input type =textid =object_to_delete_id/>
< input type =submitvalue =Delete/>
< / form>

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



同样返回一个HttpResponseRedirect到Ajax调用并没有什么意义,因为浏览器不会重定向到该页面,就像普通POST请求一样。 p>

在开发更复杂的例子之前,我建议多研究一下jquery和Ajax请求的工作原理。 ;)


I am trying to send a DELETE request from a form in Django taking help from jQuery referring following link below;

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

What I have are the following scripts;

<script src="jquery-1.11.3.js"></script>

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

(I intend to have) acting on the following form;

<form method="post" id="delete" name="delete" action="">
  {% csrf_token %}
  <input type="submit" value="Delete" />
</form>

And the following middleware;

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        

I have it added to the MIDDLEWARE_CLASSES list in my settings.py;

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',
)

It's the 3rd entry, before the CsrfViewMiddleware taking words of @Daniel Roseman into consideration.

And finally in my class based view I have the delete method delete the corresponding object;

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")                      
            )
    .
    .

I expect the middleware and the script make a DELETE request sent to the view but things ain't flying. A POST method itself is being sent. Django is finding an invalid form and gives me the response; "Form Invalid!" (else: return HttpResponse("Form Invalid!")

Please bare with me if you find stupid things here. I am new to Django and have made acquaintance with jQuery only today.

Update

I have updated the script to look like;

<script>
  $(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'}
      });
    });
  });
</script>

I have the object passed to the template as station and I have used the Django template language inside the script (var station_id = {{ station.id }}) taking inspiration from https://stackoverflow.com/a/6008968/4672736

The result is the same :/

Update

Debugging js found that the browser wasn't finding the jQuery file. Now with static files properly configured and also, the csrf protection set with help of jquery.cookie.js I have the below code in my template;

<script src="{% static "stationrunner/jquery-1.11.3.js" %}"></script>
<script src="{% static "stationrunner/jquery.cookie.js" %}"></script>

<script>
  $(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'}
      });
    });
  });
</script>

Now I have no errors on the front end but success ain't met yet. The submission of the form gets me a 200 response instead of 302.

Is this expected with an AJAX request?

It seems the request is not yet getting passed to the view as a delete request.

I tried adding success: function(){alert('Object deleted!')} to $.ajax and the alert do pop up.

Update

The final hurdle was that I had to use dashes in the custom header passed instead of underscores. I changed headers: { 'X_METHODOVERRIDE': 'DELETE' } to headers: { 'X-METHODOVERRIDE': 'DELETE' }. The letters need not be passed in capital letters too. Django will anyway convert them to capitals. So x-methodoverride or x-MeThODoveRrIDE for that matter is fine too. I don't know why dashes instead of underscores though. I figured that out as the other headers passed were carrying dashes and not underscores.

Earlier the middleware wasn't finding the key HTTP_X_METHODOVERRIDE. Now it does and my view gets a delete request :). Thanks to @baxeico for all the help.

解决方案

The problem is with your javascript code. You are submitting the form as a regular POST request and not using the $.ajax javascript code at all.

You should include jquery in a separate script tag, like this:

<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>

Then in another script tag you put your code:

<script>
    $('#delete').submit(function(e) {
        // do NOT submit the form as a regular POST request
        e.preventDefault();
        var object_to_delete_id = $('#object_to_delete_id').val();
        $.ajax({
            type: 'POST',
            url: '/your-view-url/' + object_to_delete_id,
            success: function() {
                alert('Object deleted!')
            },
            headers: { 'X_METHODOVERRIDE': 'DELETE' }
        });
    });
<script>

Here I'm assuming that you have the id of the object you want to delete in a form field like this:

<form method="post" id="delete" name="delete" action="">
  {% csrf_token %}
  <input type="text" id="object_to_delete_id" />
  <input type="submit" value="Delete" />
</form>

Please pay attention to Django CSRF protection on your Ajax call, you should write some javascript to set your CSRF cookie value in the request, as explained in the Django documentation.

Also returning a HttpResponseRedirect to an Ajax call doesn't make much sense, because the browser will not redirect to that page as it would happen with a regular POST request.

I'd suggest to study a little bit more how jquery and Ajax requests work, before digging in more complex examples like this. ;)

这篇关于从Django中的表单发送DELETE请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆