React前端无法获取Django后端未登录用户购物车数据问题排查
问题
开发电商项目时,为未认证用户实现购物车功能,采用session_id而非用户ID标识购物车。后端API文档测试正常,但前端React应用中,创建购物车功能正常,获取购物车却返回空列表。
相关代码如下:
models.py(购物车模型)
from django.db import models from books.models import Book from django.contrib.auth import get_user_model from django.dispatch import receiver from django.db.models.signals import post_save User = get_user_model() class TimeStampedModel(models.Model): created = models.DateTimeField(db_index=True, auto_now_add=True) modified = models.DateTimeField(auto_now=True) class Meta: abstract=True class Cart(TimeStampedModel): total = models.DecimalField(max_digits=10, decimal_places=2, default=0, blank=True, null=True) session_id = models.CharField(max_length=100, blank=True) class CartItem(TimeStampedModel): cart = models.ForeignKey(Cart, related_name='cart_items', on_delete=models.CASCADE) product = models.ForeignKey(Book, related_name='cart_products', on_delete=models.CASCADE) quantity = models.IntegerField(default=1) def __str__(self): return self.product.__str__()
views.py(创建购物车视图)
from django.shortcuts import get_object_or_404 from rest_framework.generics import ListCreateAPIView, CreateAPIView, ListAPIView, RetrieveUpdateDestroyAPIView, RetrieveAPIView from .serializers import CartItemSerializers, CartItemUpdateSerializers from rest_framework import permissions, status from rest_framework.response import Response from rest_framework.exceptions import NotAcceptable, ValidationError, PermissionDenied from .models import Cart, CartItem from books.models import Book from rest_framework.views import APIView import uuid # create cart view class CartItemcreateAPI(CreateAPIView): serializer_class = CartItemSerializers permission_classes = (permissions.AllowAny,) def create(self, request, *args, **kwargs): try: cart=Cart.objects.get(session_id = self.request.session['nonuser'],)#Tries to get the cart based on the users session id except: self.request.session['nonuser'] = str(uuid.uuid4())#if it doesn't exist it creates one cart = Cart.objects.create(session_id = self.request.session['nonuser'],) cart_id = cart.session_id cart = get_object_or_404(Cart, session_id=cart_id) product = get_object_or_404(Book, pk=request.data['product']) current_item = CartItem.objects.filter(cart=cart, product=product) if current_item.count()>0: raise NotAcceptable({'message':'item already in cart'}) try: quantity = 1 except Exception as e: raise ValidationError({'message':'please enter your quantity'}) if quantity>product.quantity: raise NotAcceptable({'message':'ordered quantity more than available'}) product.quantity-= quantity product.save() cart_item = CartItem(cart=cart, product=product, quantity=quantity) cart_item.save() serializer=CartItemSerializers(cart_item) cart.total += (product.price)*(quantity) cart.save() data = {'message': 'success', 'data': serializer.data} return Response(data, status=status.HTTP_201_CREATED)
存在问题的获取购物车视图
class CartItemlistAPI(ListAPIView): serializer_class = CartItemSerializers permission_classes = (permissions.AllowAny,) def get_queryset(self): try: cart = Cart.objects.get(session_id = self.request.session['nonuser'],) except: self.request.session['nonuser'] = str(uuid.uuid4()) cart = Cart.objects.create(session_id = self.request.session['nonuser'],) queryset = CartItem.objects.filter(cart=cart) return queryset
分析与解决
问题核心是前后端session不共享:API文档测试时浏览器自动维护session,但React前端跨域请求未携带正确的session cookie,导致获取购物车时生成新的session_id,对应空购物车。
1. 配置跨域请求携带Cookie
- 前端Axios配置:添加
withCredentials: true,确保请求携带Cookieaxios.defaults.withCredentials = true; - 后端Django配置:在
settings.py中开启跨域允许携带Cookie:CORS_ALLOW_CREDENTIALS = True CORS_ORIGIN_WHITELIST = [ "http://localhost:3000", # 替换为你的React前端地址 ]
2. 显式保存Session
生成新的session_id后,必须调用session.save()确保session持久化,否则新的session_id不会被返回给前端。
修改创建视图的异常处理:
except: self.request.session['nonuser'] = str(uuid.uuid4()) self.request.session.save() # 新增此行 cart = Cart.objects.create(session_id = self.request.session['nonuser'],)
修改获取视图的异常处理:
except: self.request.session['nonuser'] = str(uuid.uuid4()) self.request.session.save() # 新增此行 cart = Cart.objects.create(session_id = self.request.session['nonuser'],)
3. 验证Session一致性
在两个视图中打印self.request.session.session_key和self.request.session['nonuser'],确认创建和获取请求使用的是同一个session。如果session_key不同,说明前端未正确携带Cookie。
4. 简化Session标识逻辑
可以直接使用Django自带的request.session.session_key作为购物车标识,避免自定义nonuser键的额外管理:
# 创建视图中 try: cart = Cart.objects.get(session_id=self.request.session.session_key) except Cart.DoesNotExist: if not self.request.session.session_key: self.request.session.create() cart = Cart.objects.create(session_id=self.request.session.session_key)
内容的提问来源于stack exchange,提问作者Ayomide Adewale
相关产品推荐
相关产品推荐

