实测自定义模板过滤器:参数只能有一个;is_safe / needs_autoescape 与自动转义的配合;过滤器里的异常原样抛出;同一表达式写两次调用两次、for 里每次迭代一次,{% with %} 可缓存;不 {% load %} 会报 Invalid filter。
实测自定义模板标签:simple_tag 的参数与 as 变量;返回普通字符串会被转义、mark_safe 拼接未转义参数会 XSS;takes_context 读写上下文(循环里的写入循环外不可见);inclusion_tag 默认不带外层变量;20 处调用的渲染耗时:变量 25 µs、simple_tag 29 µs、inclusion_tag 201 µs。
实测模板继承与 block 渲染:三层继承里子覆盖父、block.super 取上一层;父链里不存在的 block 被忽略、重名 block 报错;继承层数 = 读盘次数(无 cached);include 与 extends 的差别;1/2/3 层继承渲染 5.3/10.8/21.5 µs。
实测 collectstatic:从 STATICFILES_DIRS 与各 app 的 static 收集,同名文件 STATICFILES_DIRS 优先再按 INSTALLED_APPS 顺序;增量复制比较修改时间且忽略亚秒精度(同一秒内改的文件会被漏掉);旧文件不自动删除,--clear / --dry-run / --link / -i 的行为;缺 STATIC_ROOT 报错。
实测 ManifestStaticFilesStorage:文件名加内容 MD5 前 12 位、staticfiles.json 映射;CSS 里的 url() 与 @import 被改写,外部 URL 与 data: 保持不变;内容变名字变(缓存失效);DEBUG=False 时清单缺项直接 ValueError;manifest_strict = False 的边界。
在 runserver 与 gunicorn(有无 WhiteNoise)下看静态 / 媒体文件的响应头:开发只有 Last-Modified;DEBUG=False 无 WhiteNoise 静态文件 404;WhiteNoise 给带哈希文件 max-age=315360000, public, immutable、原名 max-age=60;gzip 31600→219、br 75 字节;条件请求 304;MEDIA 不被提供。
在模板里数 QuerySet 的查询次数:同一个 QuerySet 遍历多次只查 1 次;{% for p in posts.all %}、.first、.0 各自新查;遍历里访问外键或 __str__ 里用了外键是 21 次(1 + 20),select_related 后 1 次;a.posts.count / all 每个作者一次;prefetch_related 后 2 次;传 list 给模板 0 次。
实测 Django 缓存框架的基本行为:add 不覆盖、get_or_set、incr 对不存在的 key 抛 ValueError、touch 重置过期时间;timeout 的 0 / None / 负数语义;get 无法区分「没有」与「值为 None」(用 has_key);值以 pickle 副本存取。
对比四种缓存后端:读写耗时(locmem get 2.6 µs、redis get 90 µs、db set 350 µs);gunicorn 两个 worker 下 LocMem 只命中 11/20,其它后端 20/20;Django 重启后 LocMem 丢失;LocMem 默认最多 300 条。
直接看 Redis 里的 key 实测缓存 key 生成规则:前缀:版本:key(shop:1:user:1);KEY_FUNCTION 自定义;version 与 incr_version;含空格 / 过长 key 触发 CacheKeyWarning(Redis 上照常工作);同前缀同 key 的不同应用会互相覆盖。
实测页面缓存与低级缓存:cache_page 按 URL(含查询串)+ Vary 头区分,响应头带 Cache-Control: max-age;自定义头 Vary 有效,而 Accept-Language 在 USE_I18N 下不参与 key(没有 LocaleMiddleware 时 zh 拿到 en 的缓存);带 Set-Cookie 的响应被缓存会把同一 cookie 发给所有人;{% cache %} 片段缓存。
用线程 + 模拟数据库做缓存实验:穿透(同一不存在 key 100 次 100 → 1 次数据库调用,随机 key 仍 100 次);击穿(50 并发 50 → 1 次);雪崩(相同 TTL 250ms 窗口峰值 189,TTL 抖动后 122,但总调用数更多)。