django学习笔记(4)—— Django路由系统

4. Django路由系统

4.1 路由系统基本配置

Django路由系统配置代码在urls.py中,该文件在创建项目时自动生成,一般在项目目录下。如前面建立的test_orm项目,urls.py文件就在/test_orm/test_orm/目录下。

4.1.1 路由系统URL基本格式

在urls.py文件中配置的路由,都存放在一个名为urlpatterns的变量中,这个变量是列表类型,如下所示

from django.contrib import admin
from django.urls import path,include
# 导入视图中的函数,*代表所有
from employee.views import *url
patterns = [
# 创建项目时自动生成
path('admin/', admin.site.urls),
# 用include()函数导入另一个配置文件
path('test_orm/',include('employee.urls')),
path('list_employee/',list_employee),
path('add_employee/',add_employee),
path('edit_employee/<int:emp_id>/',edit_employee),
path('del_employee/<int:emp_id>/',delete_employee),]

(1)第一行代码从django.contrib模块中导入admin函数,这个函数加载Django Admin管理后台的URL。
(2)第二行代码从django.urls模块中导入include()和path()两个函数。include()用于导入另一个URL配置文件;path()使用正则表达式匹配浏览器中的URL,把它映射到视图函数上。
(3)urlpatterns 中的每一个列表项就是一条对应关系(URL与视图函数的对应关系),这种对应关系称作URL配置(URLconf)。URL配置相当于网站的目录,可以理解为:URL配置把URL映射到相应的视图函数上,当在浏览器上访问这个URL时,通过配置项找到对应的视图函数,然后调用这个视图函数。例如,有人访问/list_employee/这个URL时,就调用views.py模块中的list_employee()视图函数。
urlpatterns中的每个列表项的格式是以下列形式进行定义的

# 导入django.urls相关模块
from django.urls import path
urlpatterns = [path (URL正则表达式,视图函数,参数,别名),]

上述代码的相关说明如下。
(1)应用路由系统必须先导入django.urls相关模块。
(2)path()中的第一个参数称为URL正则表达式,它是字符串形式。第二个参数是视图函数名,第一个参数和第二个参数是对应关系。
(3)后面两个参数是可选的,第三个参数表示可以传给视图函数的额外的参数,参数是字典类型,第四个参数给这个对应关系列表项的URL起了别名,使程序可以按名字调用这个配置项。
(4)浏览器中的网址与urlpatterns中的列表项按从上往下的顺序逐一匹配URL正则表达式,一旦匹配成功则不再继续。
(5)Django在检查URL模式时会把浏览器地址中URL前面的斜线删去,URL正则表达式中没有前导斜线,但是URL正则表达式一般以“/”结尾,这是一个默认的格式。提示:路由匹配时不包括浏览器网址的域名和端口号。如’list_employee/'可以匹配http://127.0.0.1:8000/list_employee/这个网址,其中“http://127.0.0.1:8000/”这部分自动被忽略。

4.1.2 path()的URL参数

path(‘edit_employee/< int:emp_id>/’,edit_employee)代码中,path()函数的第一个参数的角括号里的内容,称作URL参数。URL参数冒号左边为参数数据类型,右边为参数名称,如< int:emp_id>表示的参数名称为emp_id,数据类型为int。URL参数主要有以下数据类型。

  • str:匹配的任意非空字符串,但不包括分隔符“/”。
  • int:匹配0或任意正整数。
  • slug:匹配字母、数字、短横线、下划线组成的字符串。
  • uuid:匹配一个格式化的UUID(UniverallyUnique Identifier,通用唯一识别码),UUID是由数字、小写字母、破折号等组成的唯一识别码。
  • path:匹配任意非空字符串,包含分隔符“/”。

4.1.3 re_path()函数

如果path()函数不能满足精确匹配的要求,我们可以使用re_path()函数。re_path()函数中URL正则表达式中的URL参数用的是命名式分组语法,如(?P< name>pattern),其中角括号中的name是参数名,后面的pattern为待匹配的模式(正则表达式)。

from django.urls import path, re_pathfrom . import views
urlpatterns = [
# 命名式URL参数,参数名分别为year和month
re_path(data1/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/', views.test),

(1)re_path()中URL参数year通过[0-9]{4}这个正则表达式来严格匹配4位的整数,month通过[0-9]{2}这个正则表达式来严格匹配2位的整数。
(2)一个括号就是一个分组,一个分组有一个参数,因为是命名式分组,所以传给视图函数的也是命名参数。
正则表达式的用法

  • . :匹配任意单一字符。
  • \d:匹配任意一个数字。
  • \D:匹配任意非数字的字符。
  • \w:匹配字母、数字、下划线。
  • \W:匹配任意不是字母、数字、下划线的字符。
  • \s:匹配空格。
  • \S:匹配任意不是空白符的字符。
  • *:匹配零个或多个字符(例如:\d*匹配零个或多个数字)。
  • +:匹配一个或多个字符(例如:\d+匹配一个或多个数字)。
  • ?:匹配零个或一个字符(例如:\d?匹配零个或一个数字)。
  • [A-Z]:匹配A到Z中任意一个字符(大写形式)。
  • [a-z]:匹配a到z中任意一个字符(小写形式
  • [A-Za-z]:匹配a到z中任意一个字符(不区分大、小写形式)。
  • {1,3}:匹配介于一个和三个之间的字符(例如:\d{1,3}匹配一个、两个或三个数字)。

4.1.4 路由分发

一般建立项目后,在项目目录的urls.py文件中配置路由映射。如果路由越来越多,代码维护会变得困难。我们会为每个应用程序新建一个urls.py文件,将针对本应用的路由配置写在新建的文件中,这样就可以实现从根路由出发,将每个应用程序所属的URL请求,全部转发到相应的urls.py模块中。我们根据第2章中建立的myproject项目来讲解路由分发。

# 导入path()、include()函数
from django.urls import path,include
urlpatterns = [path('myapp/',include('myapp.urls')),]

上述代码的相关说明如下。
(1)路由分发使用的是include()方法,需要提前导入相应的模块path和include。
(2)include()括号内的字符串要用引号括起来,参数是导入的其他配置模块(文件),它表示的是导入的模块的路径字符串,路径以圆点分割。

提示:path()函数第一个参数(URL表达式)要包含末尾的斜杠,当Django遇到include()时,它会把path()函数第一个参数部分的字符串发送给include()导入的配置模块以做进一步处理,也就是分发到二级路由中去解析。
下一步我们建立二级路由,在/myproject/myapp文件夹中新建urls.py文件,输入以下代码

from django.urls import path
from . import views
urlpatterns = [
path('index/',views.index),path('test/', views.test),path('login/', views.login),
]

二级路由配置建立后,对应关系变成了一级路由和二级路由串联起来与视图函数的对应。如“path(‘index/’, views.index),”的实际对应关系变成“path(’ myapp/index/’, views.index),”的对应关系。

4.1.5 路由命名

在Django的URL配置中,给一个路由配置项命名,可以方便地在函数或HTML文件中调用。

urlpatterns = [
# 命名为test_filter
path('test_filter/',views.test_filter,name='test_filter'),]

上述代码的相关说明如下
(1)命名的方式较为简单,名称可以包含任何字符串,形如name=‘test_filter’。
(2)这样我们就可以在函数或HTML文件中用该名称调用URL路径。name参数可以看作URL配置项的别名。
(3)命名时要确保不发生名称冲突。如果你把一个应用的URL配置项命名为test,同时另一个应用也这么命名,在调用这个名称时就无法确定使用哪个URL。为了减少冲突,可以给URL配置项的名称加上前缀,比如加上应用程序的名称,形如myapp_name,而不仅是name。

URL配置项有个名字,我们可以通过名字得到URL,这叫作反向解析URL。反向解析URL分两种情况,一是在模板文件中反向解析,二是在函数中反向解析。

  • 模板文件(HTML文件)中使用以下代码反向解析。{% url ’ test_filter ’ %}以上代码得到URL路径为/test_filter/。
  • 在views中的函数中使用以下代码反向解析。v = reverse(’ test_filter ')以上代码使得变量v等于/test_filter/。

4.1.6 路由命名空间

引入命名空间后,可以使URL配置项名称具有唯一确定性,即使不同的应用程序使用相同的名称也不会发生冲突。也就是说,多个应用程序使用相同的名称也可以通过命名空间把它们区分开。

命名空间在URL配置项中使用namespace='name’形式指定,例如:namespace=‘app1’。举例说明,在项目根目录下的urls.py(这个配置文件称为一级配置文件)中有以下代码。

from django.urls import path,include
urlpatterns = [
# 通过include()函数导入二级配置模块,并设置命名空间
path ('app1/', include('app1.urls',namespace='app1')),
path ('app2/', include('app2.urls',namespace='app2')),
]

app01中的urls.py(二级配置文件),代码如下。

from django.urls import path,include
from app1 import views
# 指定命名空间
app_name = 'app01'
urlpatterns = [
# 给配置项命名为test
path('test/', views.test, name='test')
]

app02中的urls.py(二级配置文件),代码如下。

from django.urls import path,include
from app2 import views
app_name = 'app02'
urlpatterns = [
# 给配置项命名为test
path('test/', views.test, name='test')
]

现在,两个应用程序的URL名称重复了,我们反向解析URL的时候就可以通过命名空间的名称得到正确的URL。反向解析用“命名空间:名称”的形式,例如:app01:test。其中,app01是命名空间,test是URL配置项的名称。

  • 模板文件(HTML文件)中使用以下代码反向解析。{% url ‘app01:test’ %}以上代码得到URL路径为/app01/test/,由一、二级配置文件共同解析生成。
  • 在views中的函数中使用以下代码反向解析。v = reverse(‘app01:test’)以上代码使得变量v等于/app01/test/,这是由一、二级配置文件共同解析生成的。
    这样,即使不同应用程序的URL配置项的名称相同,都能够反向解析得到正确的URL了。提示:命名空间还可以嵌套,如group:department:index,解析时先在命名空间group中查找命名空间department,再在department中查找名称为index的URL匹配项

4.2 路由系统开发样例

4.2.1 路由系统应用的简单流程

  1. 建立路由对应关系
    第一步就是建立路径与视图函数的对应关系,打开/myproject/myproject/usls.py,在urlpatterns列表中加入以下代码
from django.urls import path
from myapp import views
urlpatterns = [
# 加入的对应关系
path('hello/',views.hello),]
  • 项目目录下的settings.py指定了位置,它通过ROOT_URLCONF变量指定,代码如下。ROOT_URLCONF = ‘myproject.urls’ 当用户在浏览器上输入http://127.0.0.1:8000/hello/时,在路由对应关系规则上实际上是访问URL /hello/,Django根据ROOT_URLCONF的设置找到urls.py文件。然后按顺序逐个匹配urlpatterns列表中的每一项,直到找到一个匹配的项;当找到这个匹配的项时就调用相关联的视图函数。
  • 按照规则,视图函数必须返回一个响应(HttpResponse 对象),Django 将响应转换成符合HTTP的响应,最后以网页的形式在浏览器上显示出来。
  1. 编写视图函数代码
    在路由配置中已经指定对应视图函数hello()为响应函数,所以第二步就是编写视图函数的代码。打开/myproject/myapp/views.py文件,编写如下代码。
from django.shortcuts import HttpResponse,render,redirect
def hello(request):
    return render(request,'hello.html')
  • 每个视图函数至少要有一个参数request,这个参数包含当前Web请求的很多信息与对象,它是django.http.Http Request类的一个实例。即使在视图函数中代码没有用request做任何事情,按照规则它必须成为视图函数的第一个参数。
  • 代码通过render()函数打开hello.html并向浏览器发送该文件形成的页面,render()函数不但能打开HTML文件,并且可以向HTML文件传递参数。
  • render()第二个参数只提供了文件名,并没有提供路径,Django如何定位文件的位置呢?实际上路径是在setttings.py中设置的。
    在settings.py文件中用以下代码先将BASE_DIR设置为“/myproject/”。
BASE_DIR =os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

然后在TEMPLATES代码块中,通过’DIRS’:[os.path.join(BASE_DIR,‘templates’)], 将模板文件的所在目录设为/myproject/templates,代码如下。

TEMPLATES = [
{'BACKEND':'django.template.backends.django.DjangoTemplates',
# 设置模板文件的所在目录
'DIRS': [os.path.join(BASE_DIR,'templates')],]

因此render()函数可根据第二个参数提供的文件名到/myproject/templates目录下寻找hello.html

  1. 编写HTML文件视图函数hello()通过render()打开hello.html文件。第三步就是编写HTML文件,在/myproject/templates/目录下,新建文件hello.html,代码如下。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello</title>
</head>
<body>
    <div align="center">
        <h2>hello world</h2>
        <hr>
        <p>看到这个页面说明程序已正常运行。</p>
    </div>
</body>
</html>

在这里插入图片描述

  1. 梳理请求过程
    从我们在浏览器中访问http://127.0.0.1:8000/hello/,到能够看到图 4.1中的页面,经过了以下6个步骤
  • 请求向后端服务器传递URL路径值/hello/。
  • Django 查看 settings.py中的ROOT_URLCONF设置,找到一级URL配置文件。一般情况下一级URL配置文件名为urls.py,并且存放在项目根目录下一个与项目名称相同的目录中,这个目录一般称为项目目录。
  • Django在urls.py中查找URL配置中的各个URL正则表达式,寻找与/hello/匹配的那个。
  • 如果能匹配URL表达式,则调用对应的视图函数。
  • 视图函数接收浏览器提交的请求,通过逻辑代码生成并返回一个Http Response对象。
  • Django把Http Response对象转换成HTTP格式的响应返回给浏览器,显示相应的页面。

4.2.2 带参数的路由应用

浏览器(客户端)发出请求时,有时会传递参数给视图函数,以实现补充请求信息的作用,这时就要在路由配置项中加上URL参数,这个参数会被对应的视图函数接收。打开/myproject/myproject/urls.py,在urlpatterns列表项中加入如下代码。

# 设置两个URL参数,名字为year和month
path('ny/<int:year>/<int:month>/',views.ny)

path函数中URL表达式有两个参数year和month,这两个参数都是int类型。路由对应的视图函数是ny(),接下来编写视图函数。打开/myproject/myapp/views.py,编写函数代码如下。

# 由于在配置项中定义了两个URL参数,所以视图函数要加上这两个参数
def ny(request,year,month):
# 参数都是int类型,需要转化成字符类型
    year1=str(year)+'年'
    month1=str(month)+'月'
    return render(request,'ny.html',{'year':year1,'month':month1})

(1)视图函数根据路由传递的参数,增加了两个参数year和month,由于路由系统中传递的是命名参数,所以在视图函数中的参数名要与其保持一致。(2)路由系统中传递的参数都是int 类型,参数传递到视图函数中会保持原来的数据类型(Django以前版本中路由传递的参数都是字符类型),因此这里要做一次数据类型转换。
(3)最后用render()函数向HTML文件传递变量,变量是字典类型,键名会成为HTML文件中的模板变量,如{{ year }}就是HTML文件的模板变量。
接下来编写HTML代码,在/myproject/templates/目录下新建文件ny.html,部分代码如下。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>带参数的URL</title>
</head>
<body>
    <div align="center">
        <h2>带参数URL测试</h2>
        <hr>
        <p>URL传入参数:1是{{ year }}, 2是{{month }}</p>
    </div>
</body>
</html>

启动程序,在浏览器地址栏中输入http://127.0.0.1:8000/ny/2021/10/并按下Enter键
在这里插入图片描述

4.2.3 带参数的命名URL配置

给URL配置项命名后,就可以在视图函数代码、模板文件中用名字调用URL配置,使URL解析工作直观化。打开/myproject/myporject/urls.py,增加一条urlpatterns匹配记录,并给这条配置项命名,代码如下。

path('ny/<int:year>/<int:month>/',views.ny,name='ny'),
# 给配置项命名为name
path('name/<str:username>/',views.name,name='name'),

上述代码的相关说明如下。
(1)第一条匹配记录命名为ny。
(2)增加了一条匹配记录并命名为name,它的URL参数名为username,是字符型参数。根据第二条匹配记录的对应关系,我们在/myproject/myaap/views.py中定义name()视图函数,代码如下。

# 定义视图函数name(),并增加一个参数username
def name(request,username):
    if username=='redirectny':
# 反向解析出地址,并通过redirect()转向这个地址
# 通过args向URL传递参数值
        return redirect(reverse('ny',args=(2021,10,)))
    else:
        welcome='欢迎您,'+username
        return render(request,'name.html',{'welcome':welcome})

上述代码的相关说明如下。
(1)通过URL名字解析出URL,称作反向解析。因为要用到反向解析函数,所以首先通过from django.urls import reverse代码语句导入reverse函数。
(2)在urls.py中定义的URL参数是命名参数username,因此视图函数name()的第二个参数名也为username,两个名字要保持一致。
(3)判断 username 是否为redirectny,如果是就转到另一个页面,对应的代码为 returnredirect(reverse(‘ny’,args=(2019,6,)))。
首先reverse()函数是反向解析函数,它的第一个参数是URL名字;第二个参数是URL参数,这个参数是元组类型,reverse(‘ny’,args=(2019,6,))将解析为/ny/2019/6/。
(4)如果username不是redirectny,就通过render()传递welcome变量值到name.html文件。

在/myproject/templates/目录下新建name.html文件,部分代码如下。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>命名URL</title>
</head>
<body>
<div align="center">
    <h2>命名url测试</h2>
    <hr>
    <p>{{ welcome }}</p> 
    <p>
        <a href="{% url 'name' '张三' %}">张三回来了</a>
    </p>
    <a href="{% url 'ny' 2021 8 %}">显示年月的页面</a>
</div>
</body>
</html>

上述代码的相关说明如下。
(1){%%}包含字符串的格式称为模板标签,Django模板系统会将其解析成不同意义的代码。代码中“{% url ‘name’ ‘张三’%}”将被解析成“/name/张三/”,这样传给视图函数name()中参数username的值是’张三’,根据代码流程会重新定向本页面,因此单击’张三回来了”这个链接会回到这个页面。在模板中{% url ‘URL名字’ 参数1 参数2 %}形式能得到反向解析的URL,其中URL名字、参数都包括在{% url %}中,URL名字要用单引号括起来,URL名字与参数、参数与参数之间用空格分隔
(2)“{% url ‘ny’ 2021 8 %}>”将被解析为“/ny/2021/8/”,也就是重定向
启动程序,在浏览器地址栏中输入http://127.0.0.1:8000/name/Tom/并按下Enter键,会看到图4.3所示的命名URL测试页面。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zyw2002

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值