路由系统
通过URL(Uniform Resource Locator,统一资源定位符)可以访问互联网上的资源——用户通过浏览器向指定URL发起请求,Web服务器接收请求并返回用户请求的资源,因此可以将URL视为用户与服务器之间交互的桥梁。
Django作为一个优秀的Web框架,提供了配置URL的路由系统,通过该路由系统,开发人员可以设计出简洁、优雅的URL。
【学习目标】:
- 学会编写URL
- 掌握URL参数的传递方法
- 掌握如何通过include()函数实现路由分发
- 熟悉URL命名与反向解析URL的方法
- 掌握URL命名空间
1.URL分发机制简介
URL的基本格式为“协议://域名或IP地址/文件名”。域名或IP地址在Web服务器中分配给Web站点。路径是网络资源在Web服务器中的逻辑路径。文件名通常与网络资源的物理文件名一致。
Django提供了灵魂的URL分发机制,允许用户使用任意格式的URL“路径/文件名”部分。如果使用常规的URL,从URL中可以分析出实际物理文件在系统中的路径和文件名。
Django接收到用户的请求后如何处理请求和返回响应的?如图2-1所示。
编辑
图 3-1 处理Http请求流程
Django接收到请求的URL后,开始执行URL分发任务,以前一节课中HelloWorld项目为例。当用户浏览器输入127.0.0.1:8000后,Django内部按如下顺序执行下列操作。
(1)启用跟URL配置模块。根URL配置模块由项目配置文件settings.py 中的ROOT_URCONF变量设置。
ROOT_URLCONF=ROOT_URLCONF = 'Helloworld.urls'
- 加载根URL配置模块,并查找变量urlpatterns。urlpatterns是一个URL模式列表,每个列表项是一个django.urls.path()或django.urls.re_path()实例,实例代码如下。
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.index),
]
- 按顺序遍历每个URL模式,在找到与请求的URL相匹配的第一个模式时停止。
- Django调用匹配的URL模式所映射的视图函数,将函数返回值作为响应结果返回给用户。视图函数接收下列参数:
- 一个HttpRequest对象实例:它封装了客户端请求的相关信息。
- URL参数:如果匹配的URL模式中嵌套了变量,则将URL路径中的匹配内容赋值给变量,将其作为参数传递给视图函数。
- Kwargs参数:向视图函数传递其他参数值。
- 如果没有找到匹配的URL模式,或者此过程中的任何位置引发错误,Django将调用错误处理视图。
****2. 路由配置
URL配置指使用URL解析函数建立URL与视图函数之间的映射关系,也就是设置访问视图函数的URL规则。
2 .1 URL解析函数
URL配置文件中的urlpatterns变量为URL解析函数的示例列表。Django提供了两个URL解析函数:django.urls.path()和django.urls.re_path()。它们的原型如下。
- path(route,view,kwargs=None,name=None)
- re_path(route,view,kwargs=None,name=None)
访问Django站点的URL基本格式为“协议://域名或IP地址/路径”。参数route为URL模式,用于匹配URL中的“路径”。参数view用于设置路径匹配时调用的视图函数。可选参数keywargs用来向views传递参数,可选参数name为URL起别名,主要在模板中使用。在URL反向解析时用URL模式的名称可获得访问视图函数的URL。
Path()和re_path()函数的第一个参数route都是字符串,而re_path()函数将route参数作为正则表达式使用。
下面回顾一下前一章节中HelloWorld项目中的urls.py文件代码。
from django.conf.urls import url
from . import views
urlpatterns = [
Path(‘', views.hello),
]
其中,“from django.conf.urls import url ”导入URL解析函数path()。“from . import views ”导入当前目录中的视图模块views(对应views.py文件)。Urlpatterns变量包含了一个URL映射。
- Path(‘', views.hello):第一个参数为空字符,用于匹配只使用域名或IP地址的URL,如“127.0.0.1:8000”。第二个参数“views.hello”设置了URL匹配时调用的视图函数。
2 .2 使用正则表达式匹配URL
若URL中包含如文件路径、工牌号这类不规则的信息,则使用路由转换器无法很好地匹配URL模式,此时可以使用正则表达式定义路由模式。若要使用正则表达式匹配URL,则可以使用re_path()函数,该函数语法格式如下:
re_path()函数的参数route接收一个正则表达式,其余参数与path()函数中参数的作用相同。正则表达式提供里一种灵活的字符串匹配方式。表2-1列出了常用的正则表达式。
表 2-1 常用的正则表达式
| 正则表达式 | 匹配说明 | |
| ^[1-9]\d*$ | 正整数 | |
| ^-[1-9]\d*$ | 负整数 | |
| ^-?[1-9]\d*$ | 整数 | |
| ^[1-9]\d* | 0$ | 非负整数(正整数 + 0) |
| ^-[1-9]\d* | 0$ | 非正整数(负整数 + 0) |
| ^[A-Za-z]+$ | 由26个英文字母组成的字符串 | |
| ^[A-Z]+$ | 由26个英文字母的大写组成的字符串 | |
| ^[a-z]+$ | 由26个英文字母的小写组成的字符串 | |
| ^[A-Za-z0-9]+$ | 由数字和26个英文字母组成的字符串 | |
| ^\w+$ | 由数字、26个英文字母或下划线组成的字符串 | |
| ^[0-9]$ | 数字 | |
| ^\d{n}$ | n位的数字 | |
| ^\d{n,}$ | 至少n位的数字 | |
| ^\d{m,n}$ | m-n位的数字 | |
| ^(0 | [1-9][0-9])$ | 零和非零开头的数字 |
| ^(- | +)?\d+(.\d+)?$ | 正数、负数、和小数 |
| ^[\u4e00-\u9fa5]{0,}$ | 汉字 | |
| ^[A-Za-z0-9]+ | 英文和数字 | |
| ^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)$ | Email地址 | |
| ^.{3,20}$ | 长度为3-20的所有字符 |
使用re_path()函数匹配包含正则表达式的URL有两种方式。
- 未命名正则表达式
若正则表达式只通过小括号“()”来捕获URL的参数,但未为其命名,则它是一个未命名正则表达式,此时捕获的参数并将其以位置参数形式传递给对应视图。
- 命名正则表达式
命名正则表达式格式为:(?Ppattern),其中name表示分组名,pattern表示匹配的正则表达式。URL匹配成功后,捕获到的参数会作为关键字参数传递给对应的视图,因此视图中的形式参数必须和正则表达式中的分组名相同。
下面的实例创建一个项目testurl,在项目同名子文件夹中定义视图,视图函数根据请求URL不同,输出不同相应的信息。
具体操作步骤如下。
- 打开pycharm工具,在终端执行下面的命令创建项目testurl。
E:>django-admin startproject testurl
- 在“testurl\testurl”文件夹下创建views.py文件,在文件中输入下面的代码定义两个视图函数。
f
from django.http import HttpResponse
def charinurl(request):
return HttpResponse('匹配大小写字母组成的字符串')
def numberinurl(request):
return HttpResponse('匹配至少两位数组组成的数字字符串')
- 打开“testurl\testurl\urls.py”文件修改代码。配置访问视图函数的URL,代码如下。
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^[A-Za-z]+$',views.charinurl), #匹配大小写字母的
re_path(r'^\d{2,}$',views.numberinurl), #匹配两位数以上的数字
]
- 在settings.py文件中,将testurl添加到INSTALLED_APP列表中,在终端输入python manage.py runserver命令,执行启动开发服务器。
- 在浏览器中访问http://127.0.0.1:8000/123abc,结果如图2-2所示。由于在“testurl.urls”中定义的URL模式中找不到123abc的匹配项,所以找不到页面的错误。
编辑图 2-2 在URL中使用式子字母混合的字符串
编辑
图 2-3 在URL中使用数字字符串
编辑图 2-4 在URL中使用字母字符串
2.2.3 路由分发
通常情况下,一个Django项目中会包含多个应用,每个应用都可以设置多个URL,如果将项目所有的URL都保存在根URLconf中,那么URLconf会变得非常臃肿,不利于维护。因此,Django允许每个应用将URL封装到本应用的URLconf中,在根URLconf使用urls模块的include()函数将应用中的URLconf导入即可实现路由分发,路由分发的使用降低应用的URLconf与根URLconf的耦合度。
使用include()实现路由分发有两种方式。
include(module,namespace = None) # 1.引入应用URLconf
include(pattern_list) # 2.引入URL模式列表
Include()函数参数的具体介绍如下。
- module:用于指定URLconf模块。
- namespace:用于指定URL模式实例的命名空间。
- pattern_list:用于指定一个可迭代的path或re_path实例列表。
下面的实例为项目testurl添加一个应用testinclude,为应用创建一个urls.py文件以配置URL访问应用的视图函数,分别使用引入应用URLconf和引入URL模式列表两种路由分发方式在项目testurl的URL配置包含应用的URL配置。
- 引入应用URLconf。
首先在项目testurl中添加应用testinclude,在testinclude中的views.py文件中定义视图函数。代码如下。
from django.http import HttpResponse
def useinclude(request):
return HttpResponse('求关注')
然后,在应用testinclude下创建urls.py 文件,为useinclude函数配置路由。
from django.urls import path,re_path
from . import views
urlpatterns = [
path('sub/',views.useinclude),
]
返回项目文件同名子文件“testurl\testurl\urls.py”文件,在文件中添加URL配置。
from django.urls import path,re_path,include
from . import views
urlpatterns = [
path('first/',include('testinclude.urls')),
]
保存修改后,在配置文件的INSTALL_APP列表中添加应用名,在浏览器中访问http://127.0.0.1:8000/first/sub/,结果如图2-5所示。
图略
本例中, path('first/',include('testinclude.urls'))包含了testinclude应用的urls.py中的URL配置。当访问first/sub/时,路由系统首先在testurl项目的跟URLconf进行URL匹配,匹配到/first/后,路由系统遍历testurl应用的URLconf,继续匹配URL其余部分,最后调用视图文件中的useinclude函数,返回响应结果。
- 引入URL模式列表
除了引用应用的URLconf,include()函数还可以引入URL模式列表,这种方式不需要再应用中新建urls.py,只需再项目的根URLconf中使用include()函数添加额外的URL模式列表即可。例如,将项目的URL配置文件修改为如下代码。
from django.urls import path,re_path,include
from . import views
from testinclude import views as subView
sub_urlpatterns = [
path('sub2/',subView.useinclude),
]
urlpatterns = [
...
path('ccit2/',include(sub_urlpatterns)),
]
在浏览器中访问http://127.0.0.1:8000/ccit2/sub2/
结果如图2-6所示。
图略
访问/ccit2/sub2/时,路由系统首先在testurl项目的根URLconf进行URL匹配,匹配到/ccit2/后路由系统遍历URL模式变量sub_urlpatterns中的元素,继续匹配URL的其余部分。