Django:管理员删除商品后如何更新会话购物车图标数量?
问题描述
我的Django项目包含store和cart两个应用:store存放所有模型,cart实现全部购物车功能,购物车基于Session实现。当管理员删除某个商品后,购物车图标显示的数量仍包含已删除商品,但购物车摘要HTML却能正确显示剩余商品(不包含已删除商品)。我尝试用post_delete信号实现管理员删除商品后自动更新购物车图标数量,但信号未生效,代码如下:
cart/signals.py
from django.db.models.signals import post_delete from django.dispatch import receiver from store.models import Product from django.contrib.sessions.models import Session @receiver(post_delete, sender=Product) def update_cart_on_product_delete(sender, instance, **kwargs): # Get all sessions sessions = Session.objects.all() for session in sessions: cart = session.get_decoded().get('cart', {}) if cart: # Check if the deleted product is in the cart if str(instance.id) in cart: del cart[str(instance.id)] # Save the updated cart back to the session session.get_decoded()['cart'] = cart session.save()
解决方案
1. 先修复信号未加载的问题
Django默认不会自动加载signals.py文件,需要在cart应用的apps.py中手动导入:
from django.apps import AppConfig class CartConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'cart' def ready(self): import cart.signals # 确保信号模块被加载
2. 修正Session数据更新逻辑
原代码中session.get_decoded()返回的是字典副本,修改副本不会同步到数据库的Session记录,需要重新编码Session数据再保存:
from django.db.models.signals import post_delete from django.dispatch import receiver from store.models import Product from django.contrib.sessions.models import Session from django.core.signing import dumps, loads @receiver(post_delete, sender=Product) def update_cart_on_product_delete(sender, instance, **kwargs): product_id = str(instance.id) sessions = Session.objects.all() for session in sessions: # 解码Session原始数据 session_data = loads(session.session_data) cart = session_data.get('cart', {}) if product_id in cart: # 删除购物车中已删除的商品 del cart[product_id] session_data['cart'] = cart # 重新编码并保存Session session.session_data = dumps(session_data) session.save()
3. 更可靠的购物车数量计算方案(推荐)
依赖信号同步Session存在性能隐患(遍历所有Session),建议在请求上下文里动态计算有效商品数量,自动过滤已删除的商品:
- 创建
cart/context_processors.py:
from store.models import Product def cart_count(request): cart = request.session.get('cart', {}) # 只统计数据库中存在的商品数量 valid_product_ids = Product.objects.filter(id__in=cart.keys()).values_list('id', flat=True) count = sum(cart[str(pid)] for pid in valid_product_ids) return {'cart_count': count}
- 在项目
settings.py的模板配置中添加上下文处理器:
TEMPLATES = [ { # ...其他配置项 'OPTIONS': { 'context_processors': [ # ...默认处理器 'cart.context_processors.cart_count', ], }, }, ]
- 模板中直接使用
{{ cart_count }}显示购物车数量即可,无需依赖Session中的缓存数据。
内容的提问来源于stack exchange,提问作者Jose Perez
相关产品推荐
相关产品推荐

