Django-路由
- 为了给一个应用设计 URL,你需要创建一个 Python 模块,通常被称为 URLconf (URL configuration)。这个模块是纯粹的 Python 代码,包含 URL 模式(简单的正则表达式)到 Python 函数(你的视图)的简单映射。
- 映射可短可长,随便你。它可以引用其它的映射。而且,因为它是纯粹的 Python 代码,它可以动态构造。
- Django 还提供根据当前语言翻译 URL 的一种方法。更多信息参见 国际化文档。
当一个用户请求 Django 站点的一个页面,下面是 Django 系统决定执行哪个 Python 代码使用的算法:
- Django 确定使用根 URLconf 模块。通常,这是
ROOT_URLCONF
设置的值,但如果传入HttpRequest
对象拥有urlconf
属性(通过中间件设置),它的值将被用来代替ROOT_URLCONF
设置。 - Django 加载该 Python 模块并寻找可用的
urlpatterns
。它是django.urls.path()
和(或)django.urls.re_path()
实例的序列(sequence)。 - Django 会按顺序遍历每个 URL 模式,然后会在所请求的URL匹配到第一个模式后停止,并与
path_info
匹配。 - 一旦有 URL 匹配成功,Djagno 导入并调用相关的视图,这个视图是一个Python 函数(或基于类的视图 class-based view )。视图会获得如下参数:
- 一个
HttpRequest
实例。 - 如果匹配的 URL 包含未命名组,那么来自正则表达式中的匹配项将作为位置参数提供。
- 关键字参数由路径表达式匹配的任何命名部分组成,并由
django.urls.path()
或django.urls.re_path()
的可选kwargs
参数中指定的任何参数覆盖。
- 一个
- 如果没有 URL 被匹配,或者匹配过程中出现了异常,Django 会调用一个适当的错误处理视图。参加下面的错误处理( Error handling )。
-
下面是一个简单的 URLconf:
1
2
3
4
5
6
7
8
9
10from 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/
将匹配列表中的第一个模式不是第二个,因为模式按顺序匹配,第一个会首先测试是否匹配。请像这样自由插入一些特殊的情况来探测匹配的次序。在这里 Django 会调用函数views.special_case_2003(request)
/articles/2003
不匹配任何一个模式,因为每个模式要求 URL 以一个斜线结尾。/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 的一部分。
- 如果路径和转化器语法不能很好的定义你的 URL 模式,你可以可以使用正则表达式。如果要这样做,请使用
re_path()
而不是path()
。 - 在 Python 正则表达式中,命名正则表达式组的语法是
(?P<name>pattern)
,其中name
是组名,pattern
是要匹配的模式。 - 这里是先前 URLconf 的一些例子,现在用正则表达式重写一下:
1
2
3
4
5
6
7
8
9
10
11
12
13from django.urls import path, re_path
from . import views
urlpatterns = [
path("articles/2003/", views.special_case_2003),
re_path(r"^articles/(?P<year>[0-9]{4})/$", views.year_archive),
re_path(r"^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$", views.month_archive),
re_path(
r"^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$",
views.article_detail,
),
] - 这实现了与前面示例大致相同的功能,除了:
- 将要匹配的 URLs 将稍受限制。比如,10000 年将不在匹配,因为 year 被限制长度为4。
- 无论正则表达式进行哪种匹配,每个捕获的参数都作为字符串发送到视图。
- 当从使用
path()
切换到re_path()
(反之亦然),要特别注意,视图参数类型可能发生变化,你可能需要调整你的视图。