我正在尝试从 Django 中的表单发送 DELETE 请求,并从 jQuery 获取帮助,参考下面的链接;
https://baxeico.wordpress.com/2014/06/25/put-and-delete-http-requests-with-django-and-jquery/
我所拥有的是以下脚本;
<script src="jquery-1.11.3.js"></script>
<script>
$(document).ready(function(){
$.ajax({
id : 'delete',
headers : {'X_METHODOVERRIDE': 'DELETE'}
});
});
</script>
(我打算)按照以下表格行事;
<form method="post" id="delete" name="delete" action="">
{% csrf_token %}
<input type="submit" value="Delete" />
</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']
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")
)
.
.
我希望中间件和脚本发出一个发送到视图的删除请求,但事情并没有发生。正在发送 POST 方法本身。 Django 发现一个无效的表单并给了我响应; “表格无效!” (else: return HttpResponse("Form Invalid!"
)
Update
我已将脚本更新为如下所示:
<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>
我将对象传递给模板station
我在脚本中使用了 Django 模板语言(var station_id = {{ station.id }}
)从中汲取灵感https://stackoverflow.com/a/6008968/4672736
结果是一样的 :/
Update
调试js发现浏览器没有找到jQuery文件。现在,静态文件已正确配置,并且在 jquery.cookie.js 的帮助下设置了 csrf 保护,我的模板中包含以下代码;
<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>
现在我的前端没有错误,但还没有成功。提交表格后我可以得到200
响应而不是302
.
这是 AJAX 请求所期望的吗?
看来该请求尚未作为删除请求传递到视图。
我尝试添加success: function(){alert('Object deleted!')}
to $.ajax
并且警报确实弹出。
Update
最后的障碍是我必须在传递的自定义标头中使用破折号而不是下划线。我变了headers: { 'X_METHODOVERRIDE': 'DELETE' }
to headers: { 'X-METHODOVERRIDE': 'DELETE' }
。这些字母也不必以大写字母传递。无论如何,Django 都会将它们转换为大写字母。所以x-methodoverride
or x-MeThODoveRrIDE
就此而言也很好。我不知道为什么用破折号而不是下划线。我发现当其他标题通过时带有破折号而不是下划线。
早些时候,中间件没有找到密钥HTTP_X_METHODOVERRIDE
。现在它出现了,我的视图收到了删除请求:)