参考文档:https://docs.djangoproject.com/zh-hans/3.2/topics/http/urls/
1. Django 如何处理一个请求
当一个用户请求Django 站点的一个页面,下面是Django 系统决定执行哪个Python 代码使用的算法:
1) Django 确定使用根 URLconf 模块。通常,这是 ROOT_URLCONF 设置的值,但如果传入 HttpRequest 对象拥有 urlconf 属性(通过中间件设置),它的值将被用来代替 ROOT_URLCONF 设置。
2) Django 加载该 Python 模块并寻找可用的 urlpatterns 。它是 django.urls.path() 和(或) django.urls.re_path() 实例的序列(sequence)。
3) Django 会按顺序遍历每个 URL 模式,然后会在所请求的URL匹配到第一个模式后停止,并与 path_info 匹配。
4) 一旦有 URL 匹配成功,Djagno 导入并调用相关的视图,这个视图是一个Python 函数(或基于类的视图 class-based view )。
视图会获得如下参数:
- 一个 HttpRequest 实例。
- 如果匹配的 URL 包含未命名组,那么来自正则表达式中的匹配项将作为位置参数提供。
- 关键字参数由路径表达式匹配的任何命名部分组成,并由 django.urls.path() 或 django.urls.re_path() 的可选 kwargs 参数中指定的任何参数覆盖。
5)如果没有 URL 被匹配,或者匹配过程中出现了异常,Django 会调用一个适当的错误处理视图。参加下面的错误处理( Error handling )。
下面是一个简单的 URLconf:
from django.urls import path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]
要从 URL 中取值,使用尖括号。
捕获的值可以选择性地包含转换器类型。
比如,使用 <int:name> 来捕获整型参数。如果不包含转换器,则会匹配除了 / 外的任何字符。
这里不需要添加反斜杠,因为每个 URL 都有。比如,应该是 articles 而不是 /articles 。
一些请求的例子:
- /articles/2005/03/ 会匹配 URL 列表中的第三项。Django 会调用函数
views.month_archive(request, year=2005, month=3)
。 - /articles/2003/03/building-a-django-site/ 会匹配 URL 列表中的最后一项。
Django 会调用函数views.article_detail(request, year=2003, month=3, slug="building-a-django-site")
路径转换器
下面的路径转换器在默认情况下是有效的:
- str - 匹配除了 ‘/’ 之外的非空字符串。如果表达式内不包含转换器,则会默认匹配字符串。
- int - 匹配 0 或任何正整数。返回一个 int 。
- slug - 匹配任意由 ASCII 字母或数字以及连字符和下划线组成的短标签。比如,building-your-1st-django-site 。
- uuid - 匹配一个格式化的 UUID 。为了防止多个 URL 映射到同一个页面,必须包含破折号并且字符都为小写。比如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID 实例。
- path - 匹配非空字段,包括路径分隔符 ‘/’ 。它允许你匹配完整的 URL 路径而不是像 str 那样匹配URL 的一部分。
2. URLconf 在什么上查找?
请求的URL被看做是一个普通的Python 字符串, URLconf在其上查找并匹配。
进行匹配时将不包括GET或POST请求方式的参数以及域名。
例如, https://www.example.com/myapp/ 请求中,URLconf 将查找 myapp/
在 https://www.example.com/myapp/?page=3 请求中,URLconf 仍将查找 myapp/ 。
URLconf 不检查使用了哪种请求方法。
换句话讲,所有的请求方法 —— 即,对同一个URL的无论是 POST请求 、 GET请求 、或 HEAD 请求方法等等 —— 都将路由到相同的函数。
3. 指定视图参数的默认值
有一个方便的小技巧是指定视图参数的默认值。 下面是一个URLconf 和视图的示例:
# URLconf
from django.urls import path
from . import views
urlpatterns = [
path('blog/', views.page),
path('blog/page<int:num>/', views.page),
]
# View (in blog/views.py)
def page(request, num=1):
# Output the appropriate page of blog entries, according to num.
...
在上面的例子中,两个URL模式都指向了相同的视图—— views.page
但是第一个样式不能在URL中捕获到任意东西。如果第一个URL模式去匹配URL,page() 函数会使用它默认参数 num=1。
如果第二个URL模式去匹配URL,page() 函数都会使用捕获到的任意 num
参数。