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

Django-Ajax报错'Uncaught ReferenceError'及传递ID至视图的正确方式

问题1:点击按钮出现 Uncaught ReferenceError: updateQuantity is not defined

原因

你定义的updateQuantity函数被包裹在docReady的回调函数内部,属于局部作用域,而按钮的onclick属性是在全局作用域下执行的,因此无法找到这个函数。

另外还有一个潜在问题:循环生成的多个元素都使用了同一个id="quantity",ID在DOM中必须唯一,后续需要改为类或自定义属性来定位对应元素。

解决方案

方案1:将函数移至全局作用域

function docReady(fn) {
  if (document.readyState === "complete" || document.readyState === "interactive") {
    setTimeout(fn, 1);
  } else {
    document.addEventListener("DOMContentLoaded", fn);
  };
};

// 把updateQuantity放在全局作用域
function updateQuantity(url, quantityElId) {
  fetch(url, {
    method: "GET",
    headers: {
      "X-Requested-With": "XMLHttpRequest",
    }
  })
  .then(response => response.json())
  .then(data => {
    document.getElementById(quantityElId).innerHTML = data.data;
  });
}

docReady(function() {
  // 其他需要DOM加载完成后执行的代码
});

模板中修改为唯一ID:

{% for item in items %}
  <div id="quantity-{{ item.id }}">{{ item.quantity }}</div>
  <button onclick="updateQuantity('parts/quotes/ajax/increase-item/{{ item.id }}', 'quantity-{{ item.id }}')">+</button>
{% endfor %}

方案2:改用事件监听(更推荐,避免全局污染)

模板去掉onclick,添加类和自定义属性:

{% for item in items %}
  <div class="quantity" data-item-id="{{ item.id }}">{{ item.quantity }}</div>
  <button class="increase-btn" data-url="parts/quotes/ajax/increase-item/{{ item.id }}">+</button>
{% endfor %}

JS代码通过事件监听绑定:

docReady(function() {
  const increaseBtns = document.querySelectorAll('.increase-btn');
  increaseBtns.forEach(btn => {
    btn.addEventListener('click', function() {
      const url = this.dataset.url;
      const quantityEl = this.previousElementSibling;
      
      fetch(url, {
        method: "GET",
        headers: {
          "X-Requested-With": "XMLHttpRequest",
        }
      })
      .then(response => response.json())
      .then(data => {
        quantityEl.innerHTML = data.data;
      });
    });
  });
});

问题2:如何通过fetch请求将ID正确传递给Django视图?

先修正你当前代码的几个错误:

  • 按钮的data-foo引号错误:应改为data-url="{{ item.get_increase_url_ajax }}"(你多写了一对引号)
  • JS选择器类名不匹配:按钮类是increase-button,但JS中用了quantity-button,需统一类名

传递ID给Django视图有两种常用方式:

方式1:URL路径参数(推荐)

1. 配置Django URL

在urls.py中定义带参数的路径:

path('parts/quotes/ajax/increase-item/<int:item_id>/', views.increase_quote_item_ajax, name='increase_item_ajax'),

2. 模板生成正确URL

使用{% url %}标签生成路径:

{% for item in items %}
  <span class="quantity">{{ item.quantity }}</span>
  <button class="increase-button" data-url="{% url 'increase_item_ajax' item.id %}">+</button>
{% endfor %}

3. Django视图接收参数

直接从URL捕获item_id:

def increase_quote_item_ajax(request, item_id):
    is_ajax = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
    if is_ajax:
        if request.method == 'GET':
            try:
                item = QuoteItem.objects.get(id=item_id)
                item.quantity += 1
                item.save(update_fields=['quantity'])
                return JsonResponse({'quantity': item.quantity})
            except QuoteItem.DoesNotExist:
                return JsonResponse({'status': 'Item not found'}, status=404)
        return JsonResponse({'status': 'Invalid request'}, status=400)
    else:
        return HttpResponseBadRequest('Invalid request')

4. JS更新视图

const buttons = document.getElementsByClassName('increase-button');
for (const button of buttons) {
  button.addEventListener('click', function (e) {
    fetch(e.target.dataset.url, {
      method: "GET",
      headers: {
        "X-Requested-With": "XMLHttpRequest",
      },
    })
    .then(response => response.json())
    .then(data => {
      button.previousElementSibling.innerHTML = data.quantity;
    })
    .catch(error => console.error('请求错误:', error));
  });
}

方式2:查询参数

如果不想修改URL结构,可将ID放在查询参数中:

1. 模板生成URL

{% for item in items %}
  <span class="quantity">{{ item.quantity }}</span>
  <button class="increase-button" data-url="parts/quotes/ajax/increase-item/?item_id={{ item.id }}">+</button>
{% endfor %}

2. Django视图接收参数

从request.GET中获取参数:

def increase_quote_item_ajax(request):
    is_ajax = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
    if is_ajax:
        if request.method == 'GET':
            item_id = request.GET.get('item_id')
            if not item_id:
                return JsonResponse({'status': '缺少商品ID'}, status=400)
            try:
                item = QuoteItem.objects.get(id=item_id)
                item.quantity += 1
                item.save(update_fields=['quantity'])
                return JsonResponse({'quantity': item.quantity})
            except QuoteItem.DoesNotExist:
                return JsonResponse({'status': '商品不存在'}, status=404)
        return JsonResponse({'status': '无效请求'}, status=400)
    else:
        return HttpResponseBadRequest('无效请求')

JS部分与方式1一致,直接使用data-url即可。

内容的提问来源于stack exchange,提问作者Viktor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 18:53:24