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

Django多购物篮(basket)架构设计咨询:自动添加至最近选中购物篮

Django 多购物篮实现方案

1. 核心模型设计

先定义关联用户、购物篮、商品的核心模型:

from django.db import models
from django.contrib.auth.models import User
from products.models import Product  # 假设已有商品模型

class Basket(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='baskets')
    name = models.CharField(max_length=100, help_text="例如'Basket #1'")
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.name} - {self.user.username}"

class BasketItem(models.Model):
    basket = models.ForeignKey(Basket, on_delete=models.CASCADE, related_name='items')
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField(default=1)

    class Meta:
        unique_together = ('basket', 'product')  # 同一商品在购物篮中仅存一条记录

2. 跟踪当前选中的购物篮

用Session存储用户当前选中的购物篮ID(会话级生效),如果需要持久化(下次登录保留),可以扩展UserProfile模型添加current_basket字段。

工具函数:获取当前购物篮

在baskets/utils.py中实现:

from django.shortcuts import get_object_or_404
from .models import Basket

def get_current_basket(request):
    if not request.user.is_authenticated:
        return None
    
    # 从Session读取当前购物篮ID
    basket_id = request.session.get('current_basket_id')
    
    # 无记录时,取用户最新创建的购物篮;无购物篮则自动创建
    if not basket_id:
        basket = request.user.baskets.order_by('-created_at').first()
        if not basket:
            basket = Basket.objects.create(
                user=request.user,
                name=f"Basket #{request.user.baskets.count() + 1}"
            )
        request.session['current_basket_id'] = basket.id
        return basket
    
    # 验证购物篮归属,避免非法ID
    try:
        return Basket.objects.get(id=basket_id, user=request.user)
    except Basket.DoesNotExist:
        return request.user.baskets.order_by('-created_at').first()

3. 购物篮切换功能

创建切换视图和页面,让用户在特定页面完成购物篮选择:

视图实现

# baskets/views.py
from django.shortcuts import redirect, render
from .models import Basket
from .utils import get_current_basket

def basket_selection(request):
    if not request.user.is_authenticated:
        return redirect('login')
    
    baskets = request.user.baskets.all()
    current_basket = get_current_basket(request)
    return render(request, 'baskets/basket_selection.html', {
        'baskets': baskets,
        'current_basket': current_basket
    })

def select_basket(request, basket_id):
    if not request.user.is_authenticated:
        return redirect('login')
    
    # 确保购物篮属于当前用户
    basket = get_object_or_404(Basket, id=basket_id, user=request.user)
    request.session['current_basket_id'] = basket.id
    return redirect('product_list')  # 切换后跳转商品列表页

切换页面模板(basket_selection.html)

<h2>选择你的购物篮</h2>
<div class="basket-list">
    {% for basket in baskets %}
        <div class="basket-item {% if basket == current_basket %}active{% endif %}">
            <a href="{% url 'select_basket' basket.id %}">{{ basket.name }}</a>
            <span>商品数量: {{ basket.items.count }}</span>
        </div>
    {% empty %}
        <p>你还没有购物篮,添加商品时会自动创建第一个。</p>
    {% endfor %}
</div>

4. 商品添加到当前购物篮

在商品页面实现添加按钮,自动关联到当前选中的购物篮:

添加商品视图

# baskets/views.py
from django.shortcuts import redirect, get_object_or_404
from products.models import Product
from .models import BasketItem
from .utils import get_current_basket

def add_to_basket(request, product_id):
    if not request.user.is_authenticated:
        return redirect('login')
    
    current_basket = get_current_basket(request)
    product = get_object_or_404(Product, id=product_id)
    
    # 商品已存在则增加数量,否则创建新条目
    basket_item, created = BasketItem.objects.get_or_create(
        basket=current_basket,
        product=product
    )
    if not created:
        basket_item.quantity += 1
        basket_item.save()
    
    return redirect('product_detail', product_id=product_id)  # 跳转回商品详情页

商品页面添加按钮模板

<!-- 在商品详情页模板中 -->
<form action="{% url 'add_to_basket' product.id %}" method="post">
    {% csrf_token %}
    <button type="submit">添加到当前购物篮:{{ current_basket.name }}</button>
</form>

5. 路由配置示例

在项目urls.py中添加路由:

from django.urls import path
from baskets import views

urlpatterns = [
    path('baskets/select/', views.basket_selection, name='basket_selection'),
    path('baskets/select/<int:basket_id>/', views.select_basket, name='select_basket'),
    path('baskets/add/<int:product_id>/', views.add_to_basket, name='add_to_basket'),
]

注意事项

  • 权限校验:所有购物篮相关视图都要校验用户登录状态,且确保操作的购物篮属于当前用户
  • 异常处理:处理Session中购物篮ID失效的情况,自动 fallback 到用户最新购物篮
  • 未登录用户:可考虑用匿名Session实现临时购物篮,后续登录时合并到用户账户

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 07:20:20