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
相关产品推荐
相关产品推荐

