context processors 是接收 request 并返回字典的函数,django 在 render() 时将其合并入模板上下文;它不是全局变量声明或自动注入魔法,仅对 render() 及其快捷方式生效,不作用于 render_to_string 等直接渲染方式。

Context Processors 是什么,不是什么
它不是模板里的全局变量声明,也不是 Django 的“自动注入”魔法。它是函数,接收 request 对象,返回一个字典;Django 在每次调用 render() 时,把所有启用的 Context Processors 返回的字典合并进模板上下文。所以它只对 render() 和基于它的快捷方式(比如 TemplateResponse)生效,对 render_to_string()、HttpResponse 直接拼接、或类视图里手动传入的 context 不起作用。
怎么写一个能用的 Context Processor 函数
必须是可调用对象,参数固定为 request,返回 dict;不能有其他参数,不能抛异常(否则整个页面 500)。常见错误包括:忘了 return、用了 self(写成类方法)、依赖未初始化的 settings 配置、在函数里做耗时操作(如数据库查询)。
- 函数必须定义在模块顶层,不能嵌套
- 返回字典的 key 就是模板里可用的变量名,value 会被直接注入
- 避免返回大对象(如 QuerySet),应提前求值或用
None占位 + 模板中判断 - 示例:
def site_info(request): return { 'SITE_NAME': 'MyApp', 'IS_STAFF': request.user.is_staff if hasattr(request, 'user') else False, }
怎么注册并让 Context Processor 生效
注册位置只有两个:要么加到 TEMPLATES 配置的 'OPTIONS']['context_processors' 列表里,要么在第三方 app 的 apps.py 中通过 ready() 动态注册(不推荐)。最常见坑是:路径写错(比如漏了 .py 文件名)、模块导入失败、没重启开发服务器、或者注册到了错误的 TEMPLATES 配置项(比如多配置时改了非默认项)。
- 路径格式是字符串,形如
'myapp.context_processors.site_info' - 必须放在
'django.template.context_processors.static'等内置 processor 之后,否则可能被覆盖 - 如果用的是
django.template.backends.django.DjangoTemplates,那它一定在TEMPLATES里;别去动TEMPLATE_CONTEXT_PROCESSORS(Django 1.8+ 已废弃)
为什么有些变量在模板里始终取不到
原因往往不是 Context Processor 写错了,而是渲染方式绕过了它。比如用 loader.get_template().render(context, request) 时,request 必须显式传入第二个参数,否则 Context Processors 根本不执行;又比如 CBV 中重写了 get_context_data() 却没调用 super(),那父类的 context 合并逻辑就断了。
立即学习“Python免费学习笔记(深入)”;
-
render_to_string(template_name, context):完全不触发 Context Processors,request参数无效 - 自定义中间件修改了
request属性,但 Context Processor 里又依赖该属性(如request.tenant),需确保中间件执行顺序早于 Context Processor - DEBUG=False 时出错静默失败,建议在函数开头加
logger.debug("CP running")排查是否被调用
request 是否存在、是否完整、以及渲染入口是否走标准流程。最容易被忽略的是:你以为“所有模板都自动有”,其实只是“所有用 render() 渲染的模板才有”。










