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

使用JS与DRF实现购物车数量追加时重复创建购物车求助

问题根源分析
  1. 前端每次点击按钮都会调用createCart发起POST请求新建购物车,完全没有尝试复用用户已有的购物车
  2. 后端Cart模型未与用户关联,无法识别当前登录用户对应的购物车,导致每次创建都是全新的独立购物车

解决方案

后端修改步骤

1. 给Cart模型添加用户关联

先在models.py中给购物车模型添加用户外键,建立用户与购物车的绑定关系:

# models.py
import uuid
from django.contrib.auth import get_user_model
from django.db import models

User = get_user_model()

class Cart(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    # 保留原有其他字段...

class CartItem(models.Model):
    cart = models.ForeignKey(Cart, on_delete=models.CASCADE, related_name='items')
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField(default=1)
    # 保留原有其他字段...

执行数据库迁移:

python manage.py makemigrations
python manage.py migrate

2. 修改CartViewSet,自动关联用户并提供获取当前用户购物车的接口

更新视图集,让创建购物车时自动绑定当前用户,同时新增接口用于获取用户已有的购物车:

from rest_framework import viewsets, mixins
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import Cart, CartItem
from .serializers import CartSerializer, AddCartItemSerializer

class CartViewSet(mixins.CreateModelMixin,
                  mixins.RetrieveModelMixin,
                  mixins.DestroyModelMixin,
                  mixins.ListModelMixin,
                  viewsets.GenericViewSet):
    queryset = Cart.objects.prefetch_related('items__product').all()
    serializer_class = CartSerializer

    def perform_create(self, serializer):
        # 创建购物车时自动绑定当前登录用户
        serializer.save(user=self.request.user)

    @action(detail=False, methods=['get'])
    def current(self, request):
        # 获取当前用户的购物车,不存在则自动创建
        cart, created = Cart.objects.get_or_create(user=request.user)
        serializer = self.get_serializer(cart)
        return Response(serializer.data)

前端修改步骤

1. 重构点击事件逻辑,先获取现有购物车再操作

不再每次点击都创建新购物车,改为先请求用户已有购物车,再添加/修改商品:

const updateBtns = document.querySelectorAll('.update-cart');
const user = '{{request.user}}';

for(let i = 0; i < updateBtns.length; i++) {
    updateBtns[i].addEventListener('click', function(){
        event.preventDefault();
        const productId = this.dataset.product;
        const action = this.dataset.action;
        
        // 先获取/创建用户购物车,再操作商品
        handleCartOperation(productId, action);
        // 保留前端cookie同步逻辑
        addCartItem(productId, action);
    });
}

function handleCartOperation(productId, action) {
    var csrftoken = getCookie('csrftoken');
    // 请求当前用户的购物车
    fetch(`/api/carts/current/`, {
        method: 'GET',
        headers:{
            'Content-Type':'application/json',
            'X-CSRFToken':csrftoken,
        },
        mode: 'same-origin',
    })
    .then(res => res.json())
    .then(cartData => {
        const cartId = cartData.id;
        // 根据操作类型添加/减少商品数量
        const quantity = action === 'add' ? 1 : -1;
        // 调用添加商品接口
        addItemToCart(cartId, productId, quantity);
    });
}

function addItemToCart(cartId, productId, quantity) {
    var csrftoken = getCookie('csrftoken');
    fetch(`/api/carts/${cartId}/items/`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-CSRFToken': csrftoken,
        },
        body: JSON.stringify({
            'product_id': productId,
            'quantity': quantity
        }),
        mode: 'same-origin',
    })
    .then(res => res.json())
    .then(data => console.log('商品操作结果:', data));
}

// 保留原有前端cookie购物车逻辑
function addCartItem(productId, action){
    let cart = JSON.parse(document.cookie.replace(/(?:(?:^|.*;\s*)cart\s*\=\s*([^;]*).*$)|^.*$/, "$1")) || {};
    
    if(action === 'add'){
        cart[productId] = cart[productId] ? {'quantity': cart[productId].quantity + 1} : {'quantity':1};
    }
    
    if(action === 'remove'){
        if(cart[productId]){
            cart[productId].quantity -= 1;
            if(cart[productId].quantity <= 0) delete cart[productId];
        }
    }
    
    document.cookie = `cart=${JSON.stringify(cart)};domain=;path=/`;
    location.reload();
}

// 移除原有的createCart函数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:37:42