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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 12:55:16