Django如何全局注入上下文使slug在所有页面导航栏生效
Django 全局共享上下文实现方案
你需要的是将公共上下文变量注入到所有模板中,Django 提供了3种常用实现方式,优先推荐使用上下文处理器:
方法1:自定义上下文处理器(最优解,全站生效)
上下文处理器是 Django 专门用于为所有模板批量注入公共变量的机制,适配导航栏这类全站通用组件的需求。
步骤1:新建上下文处理器文件
在你的app1目录下新建context_processors.py,写入以下代码:
from app2.models import Model1 def model1_global_context(request): # 初始化默认值 boolean = False model1_slug = 'app2' # 先判断用户是否登录,避免匿名用户查询报错 if request.user.is_authenticated: # 优化查询:单次查询替代先查exists再查get,减少数据库访问次数 try: user_model1 = Model1.objects.get(user=request.user) boolean = True model1_slug = user_model1.slug except Model1.DoesNotExist: pass # 返回的字典中的key可直接在所有模板中调用 return { 'model1_slug': model1_slug, 'boolean': boolean }
步骤2:注册上下文处理器
打开项目的settings.py,找到TEMPLATES配置项,将你写的处理器添加到context_processors列表中:
TEMPLATES = [ { # ... 其他原有配置 'OPTIONS': { 'context_processors': [ # ... 原有默认的上下文处理器,比如django.contrib.auth.context_processors.auth等 'app1.context_processors.model1_global_context', # 新增这行 ], }, }, ]
配置完成后所有模板都可以直接使用model1_slug和boolean变量,原有导航栏代码无需修改,你原来写在HomeView里的上下文逻辑可以直接删除。
方法2:公共视图Mixin(仅需部分视图生效时使用)
如果你不需要所有页面都注入这两个变量,只在特定类视图中使用,可以写一个公共Mixin类,所有需要该上下文的视图继承该Mixin即可:
# 可以写在app1/views.py中 class Model1ContextMixin: def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) boolean = False model1_slug = 'app2' if self.request.user.is_authenticated: try: user_model1 = Model1.objects.get(user=self.request.user) boolean = True model1_slug = user_model1.slug except Model1.DoesNotExist: pass context.update({ 'model1_slug': model1_slug, 'boolean': boolean }) return context # 原有HomeView修改为继承该Mixin class HomeView(Model1ContextMixin, ListView): model = Model1 ordering = ['-id'] template_name = 'app1/home.html' # 原有get_context_data方法可以删除
后续其他需要该上下文的类视图,只需要继承Model1ContextMixin即可。
方法3:自定义模板标签(仅在导航栏中调用,无全局污染)
如果你不想全局注入变量,也可以自定义简单模板标签,只在navbar.html中调用获取对应参数:
- 在app1下新建
templatetags目录,新增__init__.py和navbar_tags.py navbar_tags.py中写入:
from django import template from app2.models import Model1 register = template.Library() @register.simple_tag(takes_context=True) def get_model1_context(context): request = context['request'] boolean = False model1_slug = 'app2' if request.user.is_authenticated: try: user_model1 = Model1.objects.get(user=request.user) boolean = True model1_slug = user_model1.slug except Model1.DoesNotExist: pass return {'boolean': boolean, 'model1_slug': model1_slug}
- 在
navbar.html开头加载标签并调用:
{% load navbar_tags %} {% get_model1_context as model1_ctx %} {% if model1_ctx.boolean == False %} <!-- 原有导航栏逻辑,把变量替换为model1_ctx.xxx即可 -->
内容的提问来源于stack exchange,提问作者AnonymousUser
相关产品推荐
相关产品推荐

