python django官方文档地址:https://docs.djangoproject.com/zh-hans/2.1/topics/http/urls/
非常惭愧,之前还不知道看官方文档,所以这篇文章就主要是参考的官方文档url这块的文章
URL调度器
对于高质量的Web 应用来说,使用简洁、优雅的URL 模式是一个非常值得重视的细节。Django 允许你自由地设计你的URL,不受框架束缚。
首先先来了解一下Django如何处理一个请求:
- Django确定要使用的根URLconf模块。通常,这是ROOT_URLCONF设置的值,但如果传入 HttpRequest对象具有urlconf 属性(由中间件设置),则将使用其值代替 ROOT_URLCONF设置。
- Django加载Python模块并查找变量 urlpatterns。这应该是Python列表django.urls.path() 和/或django.urls.re_path()实例。
- Django依次匹配每个URL模式,在与请求的URL匹配的第一个模式停下来。
一旦其中一个URL模式匹配,Django就会导入并调用给定的视图,这是一个简单的Python函数(或基于类的视图)。视图传递以下参数:
*一个HttpRequest实例。
*如果匹配的URL模式未返回任何命名组,则来自正则表达式的匹配将作为位置参数提供。
关键字参数由路径表达式匹配的任何命名部分组成,由或者 可选kwargs参数中指定的任何参数覆盖 。 如果没有URL模式匹配,或者在此过程中的任何点期间引发异常,Django将调用适当的错误处理视图。
URL的正向解析
from django.urls import path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles//', views.year_archive),
path('articles///', views.month_archive),
path('articles////', views.article_detail),
]
就直接用官方文档的示例代码了,非常简洁
首先第一行导入path模块,然后在第二行导入视图模块,视图模块应该在接下来我会写一篇博客来详细阐述,当下的重点还是urlpatterns。
按照上面的步骤,默认加载的当前模块,此时django就开始匹配,首先要明确的一点就是,django是按照从上到下的顺序来匹配的,一旦匹配上其中一条,下面的就不会在执行,所以在写网页框架是应当注意写的顺序。
注意代码中的尖括号,在Django中尖括号的作用是捕获值,:之前式转换器的类型,后面是转换器捕获值的名称。此处应当提前说明一下,此处捕获的参数会被传入对应的views函数里面,假使函数没有声名这个参数,就会报错。
视图指定参数的默认值
有一个方便的小技巧是指定视图参数的默认值。下面是一个URLconf和视图的示例:
URLconf
from django.urls import path
from . import views
urlpatterns = [
path('blog/', views.page),
path('blog/page/', 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捕获任何内容。如果第一个模式匹配,该page()函数将使用它的默认参数num,也就是1。如果第二个模式匹配, page()将使用num捕获的任何值。
来看几个例子
- 请求/articles/2005/03/与列表中的第三个条目匹配。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/将匹配最终模式。Django会调用该函数 。views.article_detail(request, year=2003, month=3, slug="building-a-django-site")
路径转换器
默认情况下,以下路径转换器可用:
str- 匹配除路径分隔符之外的任何非空字符串'/'。如果转换器未包含在表达式中,则这是默认值。
int - 匹配零或任何正整数。返回一个int。
slug - 匹配由ASCII字母或数字组成的任何slug字符串,以及连字符和下划线字符。例如, building-your-1st-django-site。
uuid - 匹配格式化的UUID。要防止多个URL映射到同一页面,必须包含短划线并且字母必须为小写。例如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID实例。
path- 匹配任何非空字符串,包括路径分隔符 '/'。这使您可以匹配完整的URL路径,而不仅仅是URL路径的一部分str。
此外还有注册自定义转换器的操作,但是由于有正则表达式匹配的缘故,我觉得在这就先不赘述了
使用正则表达式
如果路径和转换器语法不足以定义URL模式,则还可以使用正则表达式。为此,请使用 re_path()而不是path()。
在Python正则表达式中,命名正则表达式组的语法是(?P
对前面的示例URLconf使用正则表达式重写:
from django.urls import path, re_path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
re_path(r'^articles/(?P[0-9]{4})/$', views.year_archive),
re_path(r'^articles/(?P[0-9]{4})/(?P[0-9]{2})/$', views.month_archive),
re_path(r'^articles/(?P[0-9]{4})/(?P[0-9]{2})/(?P[\w-]+)/$', views.article_detail),
]
这完成了与前一个示例大致相同的事情,除了:
- 匹配的确切网址稍微受限制。例如,年份10000将不再匹配,因为年份整数被限制为恰好四位数。
- 无论正则表达式匹配什么类型,每个捕获的参数都将作为字符串发送到视图。
使用未命名的正则表达式组
除了命名组语法之外,例如(?P
不特别推荐这种用法,因为它更容易在匹配的预期含义和视图的参数之间意外引入错误。
include的用法
在一般情况下,进行网站的编写,url不可能简简单单的只有几个,而应该是很多,此时如果将需要匹配的url全部放到urlpattern里面,肯那个就就会显得有些冗余。include函数就应运而生了。每当Django遇到时include(),它都会删除与该点匹配的URL的任何部分,并将剩余的字符串发送到包含的URLconf以进行进一步处理。
被包含的URLconf会收到来自父URLconf捕获的任何参数##
from django.urls import include, path
urlpatterns = [
# ... snip ...
path('community/', include('aggregator.urls')),
path('contact/', include('contact.urls')),
# ... snip ...
]
上面的url,community/就会跳转到aggregator.urls内部进行继续匹配
下面的这种写法也是被允许的
from django.urls import include, path
from . import views
urlpatterns = [
path('-/', include([
path('history/', views.history),
path('edit/', views.edit),
path('discuss/', views.discuss),
path('permissions/', views.permissions),
])),
]
传递额外选项
URLconfs允许您将额外的参数作为Python字典传递给视图函数。
该path()函数可以采用可选的第三个参数,该参数应该是传递给视图函数的额外关键字参数的字典。
例如:
from django.urls import path
from . import views
urlpatterns = [
path('blog//', views.year_archive, {'foo': 'bar'}),
]
在这个例子中,对于请求/blog/2005/,Django将调用 。views.year_archive(request, year=2005, foo='bar')
同样,您可以传递额外的选项,include()并且包含的URLconf中的每一行都将传递额外的选项。无论是传递给当前的url文件还是include指向的文件,都是被允许的