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

Django中如何实现公共查询,避免通知数据在多页面重复查询

Django全局通知重复查询优化方案

以下是4种可落地的优化方案,按实现成本从低到高排序:

方案1:使用Django上下文处理器全局注入(最推荐)

上下文处理器会在每个请求的模板渲染前执行一次,将通知数据注入到所有模板的上下文里,整个请求周期只会查询1次数据库,无需修改每个视图的代码。

  • 第一步:在你的app下新建context_processors.py,写入以下代码:
from .models import Notification

def user_notifications(request):
    # 未登录用户直接返回空
    if not request.user.is_authenticated:
        return {}
    # 只查未读通知,可按需加排序、分页逻辑
    notifications = Notification.objects.filter(user=request.user, is_read=False).order_by('-create_time')[:10]
    return {
        'user_notifications': notifications,
        'unread_notification_count': notifications.count()
    }
  • 第二步:在settings.py的TEMPLATES配置的OPTIONS.context_processors里加上你写的处理器:
TEMPLATES = [
    {
        # 其他原有配置不变
        'OPTIONS': {
            'context_processors': [
                # 原有默认处理器保留
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                # 新增你的处理器,替换为你实际的app名称
                'your_app_name.context_processors.user_notifications',
            ],
        },
    },
]
  • 第三步:直接在公共导航栏模板里使用{{ user_notifications }}和{{ unread_notification_count }}变量即可,所有页面无需额外传参。

方案2:自定义包含模板标签

如果不想全局注入所有模板,可以专门给导航栏写一个包含标签,仅在导航栏组件渲染时查询一次数据,代码侵入性更低。

  • 在app下的templatetags目录新建notification_tags.py:
from django import template
from ..models import Notification

register = template.Library()

@register.inclusion_tag('components/notification_bell.html')
def render_notification_bell(user):
    if not user.is_authenticated:
        return {'notifications': [], 'unread_count': 0}
    notifications = Notification.objects.filter(user=user, is_read=False).order_by('-create_time')[:10]
    return {
        'notifications': notifications,
        'unread_count': notifications.count()
    }
  • 新建导航栏通知组件模板components/notification_bell.html,写铃铛图标的渲染逻辑,直接用上面返回的变量即可。
  • 在公共导航栏模板里调用标签:{% load notification_tags %}{% render_notification_bell request.user %}

方案3:增加用户级缓存进一步降低数据库压力

如果网站访问量较大,可以对通知查询结果加缓存,同一个用户的通知在缓存有效期内只会查一次数据库:

from django.core.cache import cache

def user_notifications(request):
    if not request.user.is_authenticated:
        return {}
    # 用用户id作为缓存key,保证不同用户的通知隔离
    cache_key = f'user_notifications_{request.user.id}'
    data = cache.get(cache_key)
    if not data:
        notifications = Notification.objects.filter(user=request.user, is_read=False).order_by('-create_time')[:10]
        data = {
            'user_notifications': notifications,
            'unread_notification_count': notifications.count()
        }
        # 缓存1分钟,可按需调整时长
        cache.set(cache_key, data, 60)
    return data
  • 注意:在用户产生新通知、用户标记通知已读时,要主动删除对应用户的缓存,保证数据实时性:cache.delete(f'user_notifications_{user.id}')

方案4:前端本地存储+异步更新

如果你的项目支持前端路由跳转(比如使用Vue、React或者HTMX),可以在用户第一次访问页面时把通知数据存在localStorage,后续页面切换直接读本地数据,后台定期调用接口增量更新通知,或者用WebSocket主动推送新通知,完全避免重复查询。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 23:12:00