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
相关产品推荐
相关产品推荐

