Django 很“温柔”,它让新手几分钟就能跑起一个站点。 但真正拉开差距的,从来不是会不会写 path(),而是你是否理解路由背后的匹配机制、参数传递方式以及可扩展性设计。
这一篇,我们系统梳理 Django 路由配置的核心能力,从基础匹配,到转换器,再到动态 URL 的设计与匹配顺序问题。内容不复杂,但每一个细节都是真正写项目时绕不过去的。
1. 请求是如何被 Django 分发的
当浏览器访问:
http://127.0.0.1:8000/2003/
Django 并不是“随机找到一个函数”执行,而是有明确的分发路径:
- 请求进入 Django
- 查找
settings.py - 定位
ROOT_URLCONF - 加载主路由文件(通常是
urls.py) - 读取其中的
urlpatterns - 按顺序进行匹配
- 匹配成功后交由对应视图函数处理
可以理解为:
请求 → 主路由表 → 顺序匹配 → 命中 → 视图函数
核心点有两个:
urlpatterns是一个列表- 匹配是“自上而下”的
这两个规则后面会直接影响代码设计。
2. path() 函数的三个关键参数
在主路由中使用:
from django.urls import path
基本结构:
path(route, view, name=None)
1)route:匹配路径
第一个参数是字符串形式的路径规则。
例如:
path("2003/", ...)
表示匹配:
/2003/
如果是首页:
path("", ...)
空字符串代表根路径。
2)view:视图函数引用
第二个参数是视图函数。
注意:
传的是函数名,不加括号。
错误:
path("2003/", my_view())
正确:
path("2003/", my_view)
这里需要的是函数引用,而不是执行结果。
3)name:路由别名
第三个参数用于命名。
path("2003/", my_view, name="config_2003")
作用主要体现在模板中:
{% url 'config_2003' %}
在复杂项目里,URL 可能很长、很容易变动,使用 name 可以降低维护成本。
3. 实战:首页与固定编号页面配置
目标:
- 访问根路径 → 显示首页
- 访问 /1 → 显示编号一
- 访问 /2 → 显示编号二
路由配置
from django.urls import path
from . import views
urlpatterns = [
path("", views.index_view),
path("1/", views.page1_view),
path("2/", views.page2_view),
]
视图函数
from django.http import HttpResponse
def index_view(request):
return HttpResponse("这是我的首页")
def page1_view(request):
return HttpResponse("这是编号为一的网页")
def page2_view(request):
return HttpResponse("这是编号为 2 的网页")
这一步没有难度,但问题来了:
如果页面编号要从 3 写到 100 呢?
4. 动态路由的引入与 Path 转换器
大量重复路由意味着设计有问题。
Django 提供了转换器机制,用于匹配 URL 中的变量。
语法:
<转换器类型:变量名>
匹配到的数据会以关键字参数的形式传入视图函数。
例如:
path("<int:pg>/", views.page_view)
视图函数必须接收:
def page_view(request, pg):
变量名必须一致,否则会报错。
5. 四种常用转换器的匹配规则
1)str
匹配除斜杠之外的非空字符串。
path("user/<str:username>/", views.user_view)
2)int
匹配 0 或正整数,并自动转换为 int 类型。
path("<int:pg>/", views.page_view)
这是最常用的转换器之一。
3)slug
匹配 ASCII 字母、数字、连字符、下划线。
常用于 SEO 风格 URL,例如:
/article/how-to-learn-django/
4)path
匹配包含斜杠的非空字符串。
例如:
/goods/a/b/c
path("goods/<path:ph>/", views.goods_view)
ph 会接收 "a/b/c"
6. 动态编号页面:从 /3 到 /100
主路由改写:
urlpatterns = [
path("", views.index_view),
path("1/", views.page1_view),
path("2/", views.page2_view),
path("<int:pg>/", views.config_n_view),
]
视图函数:
def config_n_view(request, pg):
return HttpResponse(f"这是编号为 {pg} 的网页")
现在:
/3/
/10/
/88/
/100/
全部自动生效。
一条规则覆盖所有编号。
这才是“可扩展”的设计。
7. 路由匹配顺序的隐藏规则
Django 路由匹配是:
自上而下,遇到第一个匹配成功即停止。
这意味着:
具体路由必须写在动态路由前面。
错误顺序:
urlpatterns = [
path("<int:pg>/", views.config_n_view),
path("1/", views.page1_view),
]
访问 /1/ 会优先命中 <int:pg>。
因此正确写法是:
urlpatterns = [
path("1/", views.page1_view),
path("<int:pg>/", views.config_n_view),
]
顺序设计,是路由体系中最容易被忽略却最容易踩坑的点。
8. 小计算器练习:URL 参数驱动业务逻辑
目标格式:
/整数/操作符/整数
支持:
add
sub
mul
路由配置
path("<int:a>/<str:op>/<int:b>/", views.cal_view)
视图函数
def cal_view(request, a, op, b):
if op == "add":
result = a + b
elif op == "sub":
result = a - b
elif op == "mul":
result = a * b
else:
return HttpResponse("不支持的操作符")
return HttpResponse(f"计算结果为:{result}")
访问:
/10/add/5/
/10/sub/5/
/10/mul/5/
URL 本身成为参数容器。
这就是 REST 风格路由设计的基础。
关于我们
霍格沃兹测试开发学社,隶属于 测吧(北京)科技有限公司,是一个面向软件测试爱好者的技术交流社区。
学社围绕现代软件测试工程体系展开,内容涵盖软件测试入门、自动化测试、性能测试、接口测试、测试开发、全栈测试,以及人工智能测试与 AI 在测试工程中的应用实践。
我们关注测试工程能力的系统化建设,包括 Python 自动化测试、Java 自动化测试、Web 与 App 自动化、持续集成与质量体系建设,同时探索 AI 驱动的测试设计、用例生成、自动化执行与质量分析方法,沉淀可复用、可落地的测试开发工程经验。
在技术社区与工程实践之外,学社还参与测试工程人才培养体系建设,面向高校提供测试实训平台与实践支持,组织开展 “火焰杯” 软件测试相关技术赛事,并探索以能力为导向的人才培养模式,包括高校学员先学习、就业后付款的实践路径。
同时,学社结合真实行业需求,为在职测试工程师与高潜学员提供名企大厂 1v1 私教服务,用于个性化能力提升与工程实践指导。