如何通过Ajax向带CSRF保护的Django发送JSON POST请求并解析?
解决Django中Ajax发送JSON POST请求(带CSRF保护)的问题
你的问题核心在于JSON格式的POST请求和Django CSRF中间件的兼容,以及后端如何正确解析JSON数据。我帮你一步步梳理正确的实现流程:
一、前端Ajax代码的修正
你原来的写法有两个关键问题:
- 把CSRF Token放在了JSON数据里,但Django的CSRF中间件不会从JSON payload中读取
csrfmiddlewaretoken字段; - jQuery的
$.ajax在设置contentType: "application/json"时,不会自动把对象格式的data转成JSON字符串,导致发送的数据格式不对。
修改后的前端代码如下:
首先,添加一个获取CSRF Token的工具函数(从Django设置的Cookie中读取):
function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } const csrftoken = getCookie('csrftoken');
然后调整Ajax请求:
$.ajax({ type: "POST", url: '/change_ref/'+hash+"/", // 把CSRF Token放到请求头里,这是Django CSRF中间件认可的方式 headers: { 'X-CSRFToken': csrftoken }, // 手动把数据转成JSON字符串 data: JSON.stringify({"new_ref": newref}), contentType: "application/json; charset=utf-8", dataType: "json", success: function(data){ $('#changeref').modal('hide'); alert('Success!'); }, // 注意jQuery的错误回调是error,不是failure error: function(jqXHR, textStatus, errMsg) { alert('Failure! ' + errMsg); } });
二、后端视图的正确实现
Django默认的request.POST只处理表单编码的数据(application/x-www-form-urlencoded),对于JSON格式的请求,你需要从request.body中读取原始数据并解析:
import json from django.http import JsonResponse from django.views.decorators.http import require_POST @require_POST # 只允许POST请求 def change_ref_view(request, hash_value): try: # 解析JSON数据 payload = json.loads(request.body) new_ref = payload.get('new_ref') # 这里写你的业务逻辑,比如更新数据库等 # 示例:假设你有一个模型需要更新 # obj = YourModel.objects.get(hash=hash_value) # obj.ref = new_ref # obj.save() return JsonResponse({'status': 'success', 'message': 'Reference updated'}) except json.JSONDecodeError: # 处理JSON解析失败的情况 return JsonResponse({'status': 'error', 'message': 'Invalid JSON data'}, status=400) except YourModel.DoesNotExist: # 处理找不到对象的情况(根据你的业务需求调整) return JsonResponse({'status': 'error', 'message': 'Object not found'}, status=404)
三、URL配置的注意事项
确保你的URL路由正确接收hash参数,比如在urls.py中:
from django.urls import path from . import views urlpatterns = [ # 这里的<str:hash_value>对应视图中的hash_value参数 path('change_ref/<str:hash_value>/', views.change_ref_view, name='change_ref'), ]
关键原理说明
- Django的CSRF中间件会检查
X-CSRFToken请求头(或者Cookie中的csrftoken),所以发送JSON请求时必须在请求头中携带这个Token; - 当请求的
Content-Type是application/json时,Django不会自动解析数据到request.POST,必须手动读取request.body并解析为JSON对象。
内容的提问来源于stack exchange,提问作者Alberto Deca
相关产品推荐
相关产品推荐

