bigywater.tech
Django · 83

Context Processor 的执行过程

上下文处理器往每个模板里塞变量。它们什么时候运行?模板没用到也运行吗?开销多大?这篇给处理器打日志,把运行时机与次数数出来。

需要 request
render(request, …) 才运行;render_to_string 不带 request 不运行
每次渲染一遍
与模板是否用到无关;{% include %} 不重复
0.010 → 6.41 ms
加一个 5 ms 的处理器后,空模板渲染耗时

什么时候运行

实测 · 本机执行输出
render(request, "page.html") → a=B 覆盖了 A b=B  处理器调用: ['cp_a', 'cp_b']
render_to_string(无 request) → 'a= b='  处理器调用: []
render_to_string(request=req) → a=B 覆盖了 A b=B  处理器调用: ['cp_a', 'cp_b']

邮件模板常用 render_to_string 且不带 request,这时处理器变量(比如 user)都拿不到。

次数

实测 · 本机执行输出
模板里没用任何变量,处理器仍被调用: ['cp_a', 'cp_b']
模板里 include 了 2 次,处理器调用次数: 2 (一次渲染只跑一遍)
连续渲染 3 次: 6 次调用(每次渲染各一次)

所以不要在处理器里做重活(数据库查询、远程调用),或者做成惰性(返回 lazy 对象/函数,模板真的用到时才执行)——惰性做法本文没有测。

顺序与优先级

实测 · 本机执行输出
cp_a 然后 cp_b: a=B 覆盖了 A b=B  调用顺序: ['cp_a', 'cp_b']
render 里显式传 a="视图里的 a": a=视图里的 a b=B

变量名冲突时:后面的处理器覆盖前面的,视图传的 context 最高。

开销

实测 · 本机执行输出
  没有额外处理器:每次渲染中位 0.010 ms;加一个 5 ms 的处理器:6.410 ms

本实验的处理器是 time.sleep(0.005) 的人工延迟,只为说明「每次渲染都付」。

自带的

实测 · 本机执行输出
默认配置(本项目模板设置)里的 context_processors: ['context_processors.csrf', 'context_processors.request', 'cps.cp_a', 'cps.cp_b']

项目里要用 request.user 就要启用 auth 处理器,要用 messages 同理。

分步演示:上下文处理器

Context Processor
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Python 3.14.7 / Django 6.1.1(默认用 SQLite,其它数据库会在文中注明),用 django.test.Client 或真实的本机服务器进程实测;计时用 time.perf_counter,数字每次运行会有小幅抖动。处理器里打日志到文件;耗时为 40 次中位数
    • 没有验证:处理器返回 lazy 对象的效果、TemplateResponse 与处理器、Jinja2 后端下的等价机制、处理器抛异常时的错误信息
    京ICP备2026067502号-1京公网安备11010502063487号