URL配置(URLconf)就像Django所支撑网站的目录,它的本质是URL与要为该URL调用的视图函数之间的映射表;就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段业务逻辑代码对应执行。
1、什么是URL?
URL是统一资源定位器(Uniform Resource Locator)的缩写,也被称为网页地址,是因特网上标准的资源的地址。
- URL举例
http://www.sohu.com/stu/intro.html
http://222.172.123.33/stu/intro.html
- URL地址由4部分组成
第1部分:为协议:http://、ftp://等
第2部分:为站点地址:可以是域名或IP地址
第3部分:为页面在站点中的目录:stu
第4部分:为页面名称,例如 index.html
各部分之间用“/”符号隔开。
2、Django是如何处理一个请求?
当用户从Django支持的网站请求页面时,系统将使用以下算法来确定要执行的Python代码:
Django确定要使用的根URLconf模块。通常,这是ROOT_URLCONF设置的值,但是如果传入 HttpRequest对象具有urlconf 属性(由中间件设置),则将使用其值代替 ROOT_URLCONF设置。
Django加载该Python模块并查找变量 urlpatterns,涉及到 django.urls.path() 和 / 或 django.urls.re_path()实例。
Django按顺序遍历每个URL模式,并在第一个与请求的URL匹配的URL处停止,一旦其中一个URL模式匹配,Django就会导入并调用给定的views视图,该视图是Python函数(或基于类的视图)。该视图将传递以下参数:的实例对象HttpRequest。
如果匹配的URL模式不包含命名组,则根据正则表达式,完全匹配的匹配项将作为位置参数提供。
如果匹配的URL模式包含命名组,则根据正则表达式,默认非完全匹配,的匹配项将作为关键字参数提供。如果关键字参数由提供的路径表达式匹配的任何命名部分组成,这些名称部分由或 的可选kwargs参数中指定的任何参数覆盖。django.urls.path()django.urls.re_path()在Django 3.0中进行了更改:在旧版本中,带有None值的关键字参数也由未提供的命名部分组成。
如果没有URL模式匹配,或者在此过程中的任何时候引发异常,Django都会调用一个适当的错误处理视图。4xx、5xx
3、url路由系统
3.0 正则匹配的本质
正则匹配本质上帮我们做的是: re.search(“规则”, “待匹配字符串”) —> re.search(“规则”, “url路径部分”)
特点是:依照匹配规则匹配符合条件的值,匹配到则返回,否则也不会报错
自上而下匹配,当匹配成功后则停止
3.1 path 正则,完全匹配
path在匹配规则前后默认加了 ^$,保证完全匹配,
# re.search("^/books/2002/$", "/books/2002")
path('/books/2002/', views.books_2002) # 默认前后加了 ^$
path('', views.home) # 这种一般设置主页
3.2 re_path 正则,非完全匹配
re.search(“规则”,“待匹配字符串”)—> re.search(“re_path”,“url路径部分”)
3.2.0 没有分组,(request对象)
请求传参为:(request对象),例:books_2002(request) |
re_path('/books/2002/', views.books_2002) # 默认前后加了 ^$,(暂定4位匹配年份,左边规则,右边待匹配字符串)
3.2.1 无名分组(正则),按位置传参 (request对象,args位置参数)
使用简单的、没有命名的正则表达式组(通过圆括号)来捕获URL 中的值并以位置 参数传递给视图
请求传参为:(request对象,位置参数),例:year_articles(request, 2003) |
def year_articles(request, year):
return HttpResponse("年份筛选:"+year)
from django.urls import re_path
from app01 import views
urlpatterns = [
re_path(r'^articles/2003/$', views.special_case_2003), # special_case_2003(request)
re_path(r'^articles/([0-9]{4})/$', views.year_articles), # year_articles(request, 2012)
re_path(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_articles), # month_articles(request, 2003, 12)
re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.articles_detail), # views.article_detail(request, 2003, 03, 03)
]
注意:
- 若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。
- 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
- 每个正则表达式前面的’r’ 是可选的但是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不应该转义
一些请求的例子:
/articles/2005/03/ 请求将匹配列表中的第三个模式。Django 将调用函数 views.month_archive(request, '2005', '03')。
/articles/2005/3/ 不匹配任何URL 模式,因为列表中的第三个模式要求月份应该是两个数字。
/articles/2003/ 将匹配列表中的第一个模式不是第二个,因为模式按顺序匹配,第一个会首先测试是否匹配。请像这样*插入一些特殊的情况来探测匹配的次序。
/articles/2003 django会自动给URL 补齐一个反斜线结尾,将匹配列表中的第一个模式不是第二个,因为模式按顺序匹配
/articles/2003/03/03/ 将匹配最后一个模式。Django 将调用函数 views.article_detail(request, '2003', '03', '03')。
无名分组,位置参数:(有名按分组,无名按位置)
(正则):正则分组,books_year(request,d{4}) ,则分组内容作为第二个形参传过来(本质上是通过正则筛选过滤),以此类推
re_path("/books/(\d{4}/)", views.books_year)
3.2.2 有名分组 (?P<name>正则),按关键字传参 ,(request, key1=value1, key2=value2)
在更高级的用法中,可以使用命名的正则表达式组来捕获URL 中的值并以 关键字参数传递给视图。在Python 正则表达式中,命名正则表达式组的语法是(?P<name>pattern),其中 name 是组的名称,pattern 是要匹配的模式。
请求传参为:(request对象,关键字参数),例:(request, 2003, 12) |
def books_year_month(request, year, month):
return HttpResponse("月份筛选 年:"+year+" 月:" + month)
# (?P<name>正则):有名分组,关键字参数:函数传参的过程就是变量赋值的过程,
re_path(r'books/(?P<year>\d{4})/(?P<month>\d{2})/', views.books_year_month), # books_year_month(request, year=2003, month12)
3.3 路由分发,include()
与models.py和views.py一样,如果我们希望每一个app拥有自己的urls.py,则需要对全局urls.py进行分发解耦:
# 在全局设置路由分发指向
path("app01/", include("app01.urls"))
# https://127.0.0.1/app01/ 会将app01自动拼接
'''
"""djUrls URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('blog/',include('blog.urls')),
]
在blog应用下创建urls.py文件:
from django.urls import re_path
from app01 import views
urlpatterns = [
re_path('articles/(\d{4})',views.year_articles),
]