如何在Django Rest Framework中实现支持游客的数据库存储购物车?
未登录游客购物车功能实现方案
1. 修改Cart模型
首先调整模型,让user字段允许为空,同时新增session_key字段存储游客的会话标识:
from django.db import models from django.contrib.auth.models import User from .models import Product class Cart(models.Model): product = models.ForeignKey(Product, on_delete=models.CASCADE) # 允许user字段为空,适配游客场景 user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True) # 存储游客的会话唯一标识 session_key = models.CharField(max_length=40, null=True, blank=True) quantity = models.PositiveIntegerField() class Meta: # 避免同一商品重复添加:登录用户按user+product,游客按session_key+product unique_together = (('user', 'product'), ('session_key', 'product'))
2. 修改视图逻辑
移除IsAuthenticated权限限制,同时处理登录用户和未登录游客的两种场景:
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from .models import Cart from .serializers import AddToCartSerializer class AddToCartApi(APIView): serializer_class = AddToCartSerializer # 移除登录权限要求,允许游客访问 permission_classes = [] def post(self, request): serializer = self.serializer_class(data=request.data) serializer.is_valid(raise_exception=True) data = serializer.validated_data # 区分登录/未登录用户 if request.user.is_authenticated: # 登录用户:存在则更新数量,不存在则创建 cart_item, created = Cart.objects.get_or_create( user=request.user, product_id=data['product_id'], defaults={'quantity': data['quantity']} ) if not created: cart_item.quantity += data['quantity'] cart_item.save() else: # 未登录游客:先确保会话存在 if not request.session.session_key: request.session.create() session_key = request.session.session_key # 按session_key匹配购物车项,存在则累加数量 cart_item, created = Cart.objects.get_or_create( session_key=session_key, product_id=data['product_id'], defaults={'quantity': data['quantity']} ) if not created: cart_item.quantity += data['quantity'] cart_item.save() return Response({'status': 'success', 'message': '商品已添加到购物车'}, status=status.HTTP_201_CREATED)
3. 调整序列化器
确保序列化器仅处理必要字段,并验证商品合法性:
from rest_framework import serializers from .models import Product class AddToCartSerializer(serializers.Serializer): product_id = serializers.IntegerField() quantity = serializers.IntegerField(min_value=1) def validate_product_id(self, value): # 验证商品是否存在 if not Product.objects.filter(id=value).exists(): raise serializers.ValidationError("该商品不存在") return value
4. 可选:用户登录后合并购物车
当游客登录时,将会话对应的购物车商品合并到用户账户下,可通过登录信号实现:
from django.contrib.auth.signals import user_logged_in from django.dispatch import receiver from .models import Cart @receiver(user_logged_in) def merge_cart_on_login(sender, request, user, **kwargs): session_key = request.session.session_key if not session_key: return # 获取游客的购物车项 guest_cart_items = Cart.objects.filter(session_key=session_key) for item in guest_cart_items: # 合并到用户购物车,累加数量 user_cart_item, created = Cart.objects.get_or_create( user=user, product=item.product, defaults={'quantity': item.quantity} ) if not created: user_cart_item.quantity += item.quantity user_cart_item.save() # 删除游客购物车项 item.delete() # 清理会话标识 del request.session['session_key']
内容的提问来源于stack exchange,提问作者h_python_1368
相关产品推荐
相关产品推荐

