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

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),建议在请求上下文里动态计算有效商品数量,自动过滤已删除的商品:

  1. 创建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}
  1. 在项目settings.py的模板配置中添加上下文处理器:
TEMPLATES = [
    {
        # ...其他配置项
        'OPTIONS': {
            'context_processors': [
                # ...默认处理器
                'cart.context_processors.cart_count',
            ],
        },
    },
]
  1. 模板中直接使用{{ cart_count }}显示购物车数量即可,无需依赖Session中的缓存数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 04:42:03