请求进来之后,Django 怎么在 urlpatterns 里找到视图?顺序有多重要?模式多了会不会慢?这篇不靠文档,用真实的路由表逐条试,并量了不同长度路由表下的匹配耗时。
/a/5/ → a_int kwargs={'pk': 5}
/a/new/ → a_new kwargs={}
/a/abc/ → a_str kwargs={'s': 'abc'}
/a/5 → Resolver404
/first/ → first kwargs={}
/b/my-slug_1/ → b_slug kwargs={'s': 'my-slug_1'}
/b/has space/ → Resolver404
/c/x/y/z → c_path kwargs={'p': 'x/y/z'}
/c/x/y/z/ → c_path kwargs={'p': 'x/y/z/'}
/u/123e4567-e89b-12d3-a456-426614174000/ → u_uuid kwargs={'u': UUID('123e4567-e89b-12d3-a456-426614174000')}
/u/not-a-uuid/ → Resolver404
/r/2026/ → r_year kwargs={'year': '2026'}
/r/26/ → Resolver404
/nothing/ → Resolver404同一个 URL 可能符合多个模式,顺序决定结果:把具体的(a/new/)放在通用的(a/<str:s>/)之前。转换器既限定匹配范围,也决定 kwargs 里的类型。
func = user_detail
route = api/v1/users/<int:pk>/
url_name = user
namespace = 'v1'
app_names = ['api']
kwargs = {'pk': 7}
view_name = v1:userresolve() 返回的 ResolverMatch 记录了完整的 route(所有 include 前缀累加后的样子)、url_name、namespace、app_names。
GET /a/new/ → 200 GET /a/new → 301 Location: /a/new/ GET /a/new?x=1 → 301 Location: /a/new/?x=1 GET /first → 301 Location: /first/ POST /a/new → 301 DEBUG=True 时异常原文: RuntimeError: You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to testser
CommonMiddleware 在响应阶段发现 404 且 APPEND_SLASH=True、补一个斜杠就能匹配时,返回 301。GET 没问题;POST 的请求体在重定向中丢失——DEBUG=True 时 Django 用一个 RuntimeError 提醒你,DEBUG=False 时不提醒。
N=10 第 1 个 4.3 µs 中间 4.9 µs 最后 5.4 µs 不匹配 3.8 µs N=100 第 1 个 4.4 µs 中间 9.7 µs 最后 15.8 µs 不匹配 13.7 µs N=1000 第 1 个 4.4 µs 中间 60.5 µs 最后 118.1 µs 不匹配 113.2 µs N=5000 第 1 个 4.4 µs 中间 350.2 µs 最后 711.7 µs 不匹配 674.0 µs
每种规模量最快的一次(5 轮取最小值)。第一个模式的耗时和总数无关(≈4 µs),越靠后越慢,404 与匹配最后一个几乎一样——因为都要把整张表扫完。对大多数项目这不是瓶颈,但路由表上千条、并且热点路由排在后面时值得调整。(这里是 path() 且没有 include() 分层;分层会缩短每次要扫描的范围,本文没有测。)