You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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视图处理

  1. 先在urls.py配置路由:
from django.urls import path
from . import views

urlpatterns = [
    path('transaction/', views.transaction_view, name='transaction'),
]
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 05:25:42