使用Ajax与Django实现前后端数据传输遇错求排查及方案
问题分析与解决方案
先解决你遇到的「Illegal invocation」错误
这个错误大概率是因为你传入$.ajax的public_key不是字符串/数字这类原始类型,而是一个复杂对象(比如Web Crypto API生成的Key对象、DOM元素引用等)。jQuery的$.ajax在序列化data时只能处理原始值,遇到无法序列化的对象就会抛出这个错误。
先排查public_key的类型:
console.log(typeof public_key, public_key);
如果它是对象,需要先转换成字符串(比如Crypto生成的公钥,要先用btoa()或ArrayBuffer转字符串的方法处理)。
另外,Django的POST请求必须携带CSRF令牌,否则会返回403错误,你当前的代码也没处理这个,补上后完整修复代码:
async function transaction(){ // 确保public_key是字符串类型 const publicKeyStr = typeof public_key === 'object' ? JSON.stringify(public_key) : public_key; // 获取Django自动生成的CSRF令牌 const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value; $.ajax({ type: 'POST', url: '/your-transaction-url/', // 必须指定后端视图的对应URL data : { 'public_key': publicKeyStr, }, headers: { 'X-CSRFToken': csrfToken // 带上CSRF令牌 }, success: function(res){ console.log(res); }, error: function(xhr, status, err){ console.error(err); // 打印错误详情方便排查 } }); }
优雅的Django前后端数据传输方案
前端:用原生Fetch API替代jQuery(更轻量现代)
Fetch是浏览器原生API,无需依赖jQuery,代码更简洁可控:
// 绑定按钮事件(推荐用addEventListener替代onclick属性) document.getElementById('submit_transaction').addEventListener('click', async () => { try { // 处理public_key为可序列化的字符串 const publicKeyStr = typeof public_key === 'object' ? JSON.stringify(public_key) : public_key; const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value; // 发送表单编码格式的请求(对应Django的request.POST) const response = await fetch('/transaction/', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRFToken': csrfToken }, body: new URLSearchParams({ 'public_key': publicKeyStr }) }); const result = await response.json(); console.log('处理结果:', result); } catch (err) { console.error('请求失败:', err); } });
如果需要传输JSON格式数据,只需调整headers和body:
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrfToken }, body: JSON.stringify({ 'public_key': publicKeyStr })
后端:Django视图处理
- 先在
urls.py配置路由:
from django.urls import path from . import views urlpatterns = [ path('transaction/', views.transaction_view, name='transaction'), ]
- 在
views.py编写对应视图:
from django.http import JsonResponse # 处理表单编码格式的请求 def transaction_view(request): if request.method == 'POST': public_key = request.POST.get('public_key') # 这里写你的业务逻辑:比如验证公钥、执行交易、存储数据等 return JsonResponse({ 'status': 'success', 'message': '交易已处理', 'received_key': public_key }) return JsonResponse({'status': 'error', 'message': '仅支持POST请求'}, status=400) # 如果处理JSON格式的请求 def transaction_json_view(request): if request.method == 'POST': import json data = json.loads(request.body) public_key = data.get('public_key') # 业务逻辑处理 return JsonResponse({'status': 'success', 'received_key': public_key}) return JsonResponse({'status': 'error'}, status=400)
额外优化点
- 不要在HTML标签中写
onclick属性,用addEventListener绑定事件,更便于维护和分离代码 - 生产环境禁止使用
csrf_exempt装饰器,始终通过X-CSRFToken头传递令牌,Django模板中用{% csrf_token %}生成隐藏输入框即可获取令牌
内容的提问来源于stack exchange,提问作者Federico Gentile
相关产品推荐
相关产品推荐

