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

Django全局菜单优化:避免在各视图重复查询分类数据

Django全局菜单的最优实现方案

不用在每个视图里重复写分类查询,Django有两种常用的优雅方案解决这个问题:

1. 全局上下文处理器

这是最省心的方案,能让所有模板自动拿到categories变量:

  • 在你的应用目录下新建context_processors.py文件,写一个返回分类数据的函数:
from .models import Category

def menu_categories(request):
    # 可按需添加过滤条件,比如只展示启用状态的分类
    return {
        'categories': Category.objects.all()
    }
  • 打开项目的settings.py,找到TEMPLATES配置,在OPTIONS['context_processors']里添加这个处理器的路径:
TEMPLATES = [
    {
        # 其他配置项...
        'OPTIONS': {
            'context_processors': [
                # 保留原有处理器...
                'yourapp.context_processors.menu_categories',
            ],
        },
    },
]

完成后所有模板(包括你的index.html)都能直接使用{% for category in categories %},无需在任何视图里手动传递该变量。

2. 自定义包含模板标签

如果菜单需要更灵活的控制(比如不同页面展示不同样式、支持传参),这个方案更合适:

  • 在应用目录下新建templatetags目录,里面创建__init__.py和menu_tags.py两个文件
  • 在menu_tags.py里编写包含标签:
from django import template
from .models import Category

register = template.Library()

@register.inclusion_tag('menu_snippet.html')  # 指向菜单片段模板
def render_menu():
    categories = Category.objects.all()
    return {'categories': categories}
  • 新建menu_snippet.html模板片段,写菜单的循环逻辑:
<ul class="menu">
    {% for category in categories %}
        <li><a href="/category/{{ category.slug }}">{{ category.name }}</a></li>
    {% endfor %}
</ul>
  • 在index.html里加载标签并调用:
{% load menu_tags %}
{% render_menu %}

优化建议:添加缓存

分类数据通常不会频繁更新,给查询加缓存能大幅减少数据库压力:
比如把上下文处理器的代码改成:

from django.core.cache import cache
from .models import Category

def menu_categories(request):
    categories = cache.get('global_menu_categories')
    if not categories:
        categories = list(Category.objects.all())
        cache.set('global_menu_categories', categories, 3600)  # 缓存1小时
    return {'categories': categories}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 05:12:13