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

Django模板JS适配多类商品购物车功能故障排查

电商购物车跨类别添加报错问题排查与解决

问题描述

基于Django开发类似amazon.in、flipkart.com的电商Web应用,使用通用模板展示各类别商品页面,通过嵌入JS结合LocalStorage实现“加入购物车”功能。出现以下问题:

  • 首次进入商品页面点击“加入购物车”,JS正常执行,商品成功存入LocalStorage;
  • 返回商品列表页进入另一类别商品页面后,点击按钮无响应,控制台抛出Uncaught TypeError错误,无法添加商品;
  • 清空LocalStorage后可再次正常添加,但切换类别后又触发相同错误。

相关代码

商品视图模板代码(含嵌入JS)

{% extends 'MenuCategory/Navigation_bar.html' %}
{% block title %} {{Category.Item_Category}} {% endblock %}
{% block style %}
{% endblock %}
{% block head %}
{% endblock %}
{% block body %}
<div class="container-fluid mt-3">
    <div class="list-group">
        {% for item in Content %}
        <a href="#" class="list-group-item list-group-item-action" aria-current="true">
            <div class="row">
                <div class="col-1 d-flex align-items-center">
                    <img src="/media/{{item.Item_Image}}" class="rounded img-fluid" width="150px" height="150px">
                </div>
                <div class="col-8">
                    <div class="d-flex w-100 row">
                        <h5 id="nameby{{Category.Item_Category}}Product{{item.Item_ID}}" class="mb-1">{{item.Item_Name}}</h5>
                        <div class="d-flex w-100 row">
                            <p class="mb-1">{{item.Item_Description}}</p>
                        </div>
                        <div class="d-flex w-100 row">
                            <small id="PriceOf{{Category.Item_Category}}Product{{item.Item_ID}}">{{item.Item_Price}}</small>
                        </div>
                    </div>
                </div>
                <div class=" col-3 d-flex justify-content-end align-items-center mr-2">
                    <span id="btnspan{{Category.Item_Category}}Product{{item.Item_ID}}" class="AddBtn">
                        <button id="{{Category.Item_Category}}Product{{item.Item_ID}}" class="btn btn-primary {{Category.Item_Category}}CartButton">Add to Cart</button>
                    </span>
                </div>
            </div>
        </a>
        {% endfor %}
    </div>
</div>
{% endblock %}
{% block script %}

document.getElementById("NavbarMainHeading").innerHTML="{{Category.Item_Category}}";
function updateCart(Cart) {
    for (let item in Cart) {
        console.log(item)
        document.getElementById('btnspan' + item).innerHTML = `<button id="minus${item}" class="btn btn-primary minus">-</button><span id="val${item}">${Cart[item][0]}</span><button id="plus${item}" class="btn btn-primary plus">+</button>`
    }
    localStorage.setItem('Cart', JSON.stringify(Cart))
    console.log(localStorage.getItem('Cart'))
}


if (localStorage.getItem('Cart') == null) {
    var Cart = {};
} else {
    Cart = JSON.parse(localStorage.getItem('Cart'))
    updateCart(Cart)
}

let btns = document.getElementsByClassName('{{Category.Item_Category}}CartButton');
btns = Array.from(btns);
for (let i = 0; i < btns.length; i++) {
    btns[i].addEventListener('click', function() {
        var idstr = this.id.toString();
        if (Cart[idstr] != undefined) {
            Cart[idstr][0] = Cart[idstr][0] + 1;

        } else {
            name = document.getElementById("nameby" + idstr).innerHTML;
            price = document.getElementById("PriceOf" + idstr).innerHTML;
            quantity = 1;
            Cart[idstr] = [quantity, name, parseInt(price)];
        }
        updateCart(Cart)
    })
}

{% endblock %}

urls.py代码

from django.urls import path,include
from . import views
urlpatterns = [
    # path('admin/', admin.site.urls),
    path('',views.CategoryPage,name='MenuCategoryPage'),
    path('Category/<str:Variety_Name>',views.Category_Items,name='CategoryItems')
]

views.py代码

from django.shortcuts import render
from django.http import HttpResponse
from .models import Varieties,CategoryItems
def Category_Items(request,Variety_Name):
    print(f"variety name {Variety_Name}")
    post=CategoryItems.objects.filter(Item_Category=Variety_Name)
    Category=None
    print(len(post))
    if len(post) >= 1:
        Category=post[0]
    content={'Content':post,'Category':Category}


    return render(request,'MenuCategory/Product_List.html',content)

models.py代码

from django.db import models

# Create your models here.
class Varieties(models.Model):
    VarietyID=models.AutoField(primary_key=True)
    Variety_Name=models.CharField(max_length=50,default='Variety name should be within 50 characters.')
    Variety_Image=models.ImageField(default='')

    def __str__(self):
        return self.Variety_Name
class CategoryItems(models.Model):
    Item_ID=models.AutoField(primary_key=True)
    Item_Category=models.CharField(max_length=50,default="Variety Name and Category Name must be same.")
    Item_SubCategory=models.CharField(max_length=50,default="SubCategory Name")
    Item_Image=models.ImageField(default='')
    Item_Name=models.CharField(max_length=50,default='Ex: Paneer Pratha')
    Item_Price=models.IntegerField()
    Item_Description=models.CharField(max_length=1000,default='Write Something about speciality of the Product.')
    def __str__(self):
        return f"{self.Item_Name} - {self.Item_Category}"

错误情况

  • 购物车已有商品时添加其他类别商品,控制台报错:
    切换类别添加商品报错
  • LocalStorage为空时可正常添加商品:
    空购物车时正常添加

问题原因

核心问题在updateCart函数:页面加载时会遍历LocalStorage中所有购物车商品,尝试修改对应btnspan{itemId}元素的innerHTML。但当前页面仅显示当前类别的商品,其他类别的商品DOM元素不存在,调用document.getElementById('btnspan' + item)返回null,执行.innerHTML时抛出TypeError: Cannot set properties of null (setting 'innerHTML'),导致后续JS代码终止,新的添加购物车事件监听无法正常工作。


解决方案

修改updateCart函数,仅对当前页面存在的DOM元素进行更新,跳过不存在的元素:

function updateCart(Cart) {
    for (let item in Cart) {
        console.log(item)
        const btnSpan = document.getElementById('btnspan' + item);
        // 仅在元素存在时更新内容
        if (btnSpan) {
            btnSpan.innerHTML = `<button id="minus${item}" class="btn btn-primary minus">-</button><span id="val${item}">${Cart[item][0]}</span><button id="plus${item}" class="btn btn-primary plus">+</button>`;
        }
    }
    localStorage.setItem('Cart', JSON.stringify(Cart))
    console.log(localStorage.getItem('Cart'))
}

额外优化购物车数据初始化逻辑,避免解析失败导致的异常:

// 替换原Cart初始化代码
let Cart = {};
if (localStorage.getItem('Cart')) {
    try {
        Cart = JSON.parse(localStorage.getItem('Cart'));
        updateCart(Cart);
    } catch (e) {
        console.error('解析购物车数据失败', e);
        localStorage.removeItem('Cart');
    }
}

修改后,切换类别页面时只会更新当前页面存在的商品按钮,不会因找不到DOM元素报错,新的添加购物车按钮可正常绑定事件。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 03:21:02