如何在Django中高效提取多个视图的通用上下文?
提取Django视图通用上下文变量的方案
假设我们有两个或多个视图,每个视图的模板都继承自base.html,且base.html文件中包含上下文变量project_name和company_name:
文件 base.html
<!DOCTYPE html> <html> <head> <title>{{ project_name }}</title> </head> <body> {{ company_name }} {% block content %}{% endblock %} </body> </html>
当前我们需要在每个视图中重复添加这两个通用上下文变量,代码如下:
文件 views.py
def view1(request): context = { "view1 data": "some data", "project_name": "Project Name", "company_name": "Company Name", } return render(request, "view1.html", context) class View2(DetailView): template_name = "view2.html" model = SampleModel def get_context_data(self, **kwargs): context = super(View2, self).get_context_data(**kwargs) context["view2 data"] = "sample data" context["project_name"] = "Project Name" context["company_name"] = "Company Name" return context
我们需要优化代码,将project_name和company_name这两个通用上下文提取到其他位置,同时让base.html仍能正常获取这些变量,最终视图代码如下:
期望的views.py
def view1(request): context = { "view1 data": "some data", } return render(request, "view1.html", context) class View2(DetailView): template_name = "view2.html" model = SampleModel def get_context_data(self, **kwargs): context = super(View2, self).get_context_data(**kwargs) context["view2 data"] = "sample data" return context
由于基于函数的视图(FBV)和基于类的视图(CBV)工作机制不同,下面提供几种针对性的解决方案:
方案一:全局上下文处理器(推荐,同时支持FBV和CBV)
Django的上下文处理器可以全局注入通用变量,所有模板都能直接访问:
- 在你的应用目录下创建
context_processors.py文件,编写通用上下文函数:
def common_context(request): return { "project_name": "Project Name", "company_name": "Company Name" }
- 在项目的
settings.py中,找到TEMPLATES配置,将上述处理器添加到context_processors列表:
TEMPLATES = [ { # 保留原有配置项... 'OPTIONS': { 'context_processors': [ # 原有处理器(比如django.contrib.auth.context_processors.auth等) 'your_app_name.context_processors.common_context', ], }, }, ]
配置完成后,所有视图对应的模板都能直接使用project_name和company_name,无需在视图中重复定义。
方案二:针对FBV的自定义渲染函数
如果不想全局注入,可封装一个包含通用上下文的自定义渲染函数:
from django.shortcuts import render def custom_render(request, template_name, context=None): # 定义通用上下文 common_ctx = { "project_name": "Project Name", "company_name": "Company Name" } # 合并视图自定义上下文 if context: common_ctx.update(context) return render(request, template_name, common_ctx)
然后在FBV中使用这个函数替代原生render:
def view1(request): context = { "view1 data": "some data", } return custom_render(request, "view1.html", context)
方案三:针对CBV的Mixin类
对于CBV,可通过编写Mixin类来复用通用上下文逻辑:
from django.views.generic.detail import DetailView class CommonContextMixin: def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 添加通用上下文 context.update({ "project_name": "Project Name", "company_name": "Company Name" }) return context
让你的CBV继承这个Mixin(注意Mixin要放在视图基类之前):
class View2(CommonContextMixin, DetailView): template_name = "view2.html" model = SampleModel def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["view2 data"] = "sample data" return context
内容的提问来源于stack exchange,提问作者Jobo Fernandez
相关产品推荐
相关产品推荐

