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

如何修复基于信号的动态内容缓存中新增分类无法实时显示问题?

问题根源

  1. 缓存键未区分用户:全局缓存键category会导致不同用户的分类列表互相覆盖,且信号仅删除全局缓存,无法精准失效当前用户的缓存。
  2. 缓存对象存在惰性问题:直接缓存QuerySet(惰性求值对象)可能导致取出时无法实时获取数据库最新数据。
  3. 信号未精准针对用户缓存:原信号删除的是全局缓存键,无法确保当前用户的缓存被正确清理。

修复方案

1. 为每个用户生成独立缓存键

修改ShowCategories视图的get_queryset方法,将用户ID加入缓存键,确保每个用户的缓存独立存储:

class ShowCategories(LoginRequiredMixin, ListView):
    paginate_by = 10
    model = Category
    context_object_name = 'categories'
    template_name = 'expense_tracker/category_list.html'

    def get_queryset(self):
        # 生成带用户ID的专属缓存键
        cache_key = f'category_list_{self.request.user.id}'
        categories = cache.get(cache_key)
        
        if categories is None:
            # 转换为列表缓存,避免QuerySet惰性求值问题
            categories = list(Category.objects.filter(user=self.request.user))
            # 设置缓存并添加过期时间(示例为15分钟)
            cache.set(cache_key, categories, 60*15)
        
        # 将列表转回QuerySet,适配ListView分页需求
        return Category.objects.filter(id__in=[cat.id for cat in categories])

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = 'Категории'
        return context

2. 修改信号处理逻辑,精准清理用户缓存

更新信号代码,根据操作的分类所属用户,删除其对应的缓存键:

from django.db.models.signals import post_delete, post_save
from django.dispatch import receiver
from .models import Category
from django.core.cache import cache

@receiver(post_delete, sender=Category)
def category_post_delete_handler(sender, instance, **kwargs):
    cache_key = f'category_list_{instance.user.id}'
    cache.delete(cache_key)

@receiver(post_save, sender=Category)
def category_post_save_handler(sender, instance, **kwargs):
    cache_key = f'category_list_{instance.user.id}'
    cache.delete(cache_key)

3. 确保信号被正确注册

将信号代码放在app的signals.py文件中,然后在apps.py中配置加载逻辑:

# expense_tracker/apps.py
from django.apps import AppConfig

class ExpenseTrackerConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'expense_tracker'

    def ready(self):
        # 导入信号确保Django启动时注册
        import expense_tracker.signals

最后在settings.py的INSTALLED_APPS中替换原app配置:

INSTALLED_APPS = [
    # ...
    'expense_tracker.apps.ExpenseTrackerConfig',
    # 替换原来的'expense_tracker'
]

关键说明

  • 缓存列表而非原始QuerySet:避免惰性求值导致的旧数据问题,同时通过ID过滤转回QuerySet适配ListView分页。
  • 专属缓存键:彻底解决多用户缓存互相干扰的问题,确保缓存失效仅影响操作的用户。
  • 缓存过期时间:作为信号失效的兜底方案,避免极端情况下缓存长期不更新。

内容的提问来源于stack exchange,提问作者Kozorez-V

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 14:33:38