第3章 初探路由
3.1 路由定义规则
路由称为URL,也可以称为URLconf,是对可以从互联网上得到的资源位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每一个文件都有一个唯一的路由,用于指出网站文件的路径位置。简单地说,路由可视为我们常说的网址,每个网址代表不同的网页。
3.1.1 Django 路由定义
完整的路由包含:路由地址、视图函数、可选变量和路由命名。其中,基本的信息必须有:路由地址和视图函数,路由地址即我们常说的网址,视图函数即 App 的views.py 文件所定义的函数或类。
在讲解路由定义之前,我们可以在每一个创建的 App 项目中创建一个 urls.py 文件,这一步的原因是,我们将所有属于各自 App 的路由都写入各自项目的路由文件中,这样跟容易区分和管理每个 App 的路由地址,而根目录的 urls.py 文件是将每个 App 的路由地址统一管理。对所有 App 的路由统一管理的代码如下。
在 django1 文件里的 urls.py 文件里,做如下修改:
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
# 指向内置 Admin 后台系统的路由文件 sites.py
path('admin/', admin.site.urls),
# 指向 App1 的路由文件 urls.py
path('',include('App1.urls')),# 通常为首页地址
]
由于首页地址分发给 App1 的 urls.py 文件处理,因此需要对 App1 的 urls.py 文件编写路由信息:
from django.urls import path
from App1 import views
urlpatterns = [
path('',views.index)
]
由于上面使用了 views.py 文件里的 index 函数,所以需要再 views.py 文件里定义 index 函数,代码如下:
from django.shortcuts import render
# Create your views here.
def index(request):
value = 'This is test!'
print(value)
return render(request,'index.html')
在 templates 文件夹里创建一个 index.html 文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 style="color: red">Hello World</h1>
</body>
</html>
3.1.2 路由变量的设置
在日常开发中,有时一个路由可以代表多个不同的页面。因此,Django 在定义路由时,可以对路由设置变量值,使路由具有多样性。
路由的变量类型有字符类型、整数、slug和uuid,最为常用的是字符类型和整型。各个类型说明如下:
- 字符类型:匹配任何非空字符串,但不含斜杆。如果没有指定类型,就默认使用该类型。
- 整型:匹配0和正整数。
- slug:可理解为注释、后缀或附属等概念,常作为路由的解释性字符,可匹配ASCII字符以及连接符和下划线,能使路由更加清晰易懂。
- uuid:匹配一个uuid格式的对象。为了防止冲突,规定必须使用"-"并且所有字母小写。
在应用项目中添加下面一段路由:
path('<year>/<int:month>/<slug:day>',views.time),
然后在 views 文件了编写函数
def time(request,year,month,day):
return HttpResponse(str(year)+'/'+str(month)+'/'+str(day))
然后再浏览器地址中填写 http://127.0.0.1:10086/2024/03/16,返回结果:
除了在路由地址设置变量外,Django 还支持在路由地址外设置变量(路由的可选变量)。
# App1 的 urls.py
from django.urls import path
from App1 import views
urlpatterns = [
# 指定变量的值
path('',views.index,{'month':'2024/03/16'}),
path('<year>/<int:month>/<slug:day>',views.time),
]
# App1 的 views.py
from django.shortcuts import render,HttpResponse
# Create your views here.
def index(request,month):
# value = 'This is test!'
# print(value)
# return render(request,'index.html')
return HttpResponse('这是路由地址之外的变量'+month)
def time(request,year,month,day):
return HttpResponse(str(year)+'/'+str(month)+'/'+str(day))
路由函数的第三个参数设置规则如下:
- 参数只能以字典的形式表示。
- 设置的参数只能在视图函数中读取和使用。
- 字典的一个键值对代表一个参数,键值对的键代表参数名,键值对的值代表参数值。
- 参数值没有数据格式限制,可以为某个实例对象、字符串或列表等。
3.1.3 正则表达式的路由定义
为了进一步规范某些数据格式,可以使用正则表达式限制路由地址变量的取值范围。如下为设置规范日期格式的代码:
(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})
路由的正则表达式是由路由函数 re_path 定义的,其作用是对路由变量进行截取与判断。正则表达式是以小括号为单位的,每个小括号的前后可以使用斜杆或者其他字符将其分隔与结束。
-
?P 是固定格式,字母P必须为大写。
-
为变量名。 -
[0-9]{4}是正则表达式的匹配模式,代表变量的长度为4,只允许取0~9的值。
然后,我们需要再视图层进行变量的设置:
def mydate(request,year,month,day):
return HttpResponse(str(year)+'/'+str(month)+'/'+str(day))
3.2 命名空间与路由命名
网站规模越大,其网页的数量就越多,如果网站的网址过多,在管理或者维护上就会存在一定的难度。Django 为了更好的管理和使用路由,可以为每条路由设置命名空间或路由命名。
3.2.1 命名空间 namespace
在 django1 文件夹的 urls.py 中重新定义路由信息,分别指向各 App 里的 urls.py 文件。
path('',include(('App1.urls','App1'),namespace='index')),
path('user/',include(('App2.urls','App2'),namespace='user')),
路由函数 include 设有参数 arg 和 namespace ,参数 arg 指向项目应用 App 的 urls.py 文件,其数据格式以元组或字符串表示;可选参数 namespace 是路由的命名空间。
若要对路由设置参数 namespace,则参数 arg 必须以元组格式表示,并且元组的长度必须为2,元组的元素说明如下:
- 第一个元素为项目应用的 urls.py 文件。
- 第二个元素可以自行命名,但不能为空。
3.2.2 路由命名
在上述命名空间的基础上,分别在 app 里重新定义路由。
path('',views.index,{'date':'2024/03/16'},name='index'),
path('<year>/<int:month>/<slug:day>',views.time,name='date'),
3.3 路由的使用方式
路由为网站开发定义了具体的网址,不仅如此,它还能被其他功能模块使用,比如视图、模版、模型、Admin后台或表单等。
3.3.1 在模版中使用路由
以上的路由命名可以在我们创建的 html 文件中使用,这样更加方便。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 style="color: red">Hello World</h1>
<br>
<a href="{% url 'date' '2024' '04' '01' %}">查看日期</a>
</body>
</html>
以上传入的 date 就是使用路由命名的。
模版语法 url 的参数设置与路由定义是相互关联的,具体说明如下:
-
若路由地址存在变量,则模版语法 url 需要设置相应的参数值,参数值之间使用空格隔开。
-
若路由地址不存在变量,则模版语法只需设置路由命名 name 即可。
当命名空间被定义后,语法也会发生变化。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 style="color: red">Hello World</h1>
<br>
<a href="{% url 'index:date'%}">查看日期</a>
</body>
</html>
如果同时定义了命名空间和路由命名,那么在模版传递的必须是命名空间和路由命名合起来的值。
3.3.2 反向解析 reverse 与 resolve
路由除了在模版中使用,还可以在视图里使用。Django 的请求生命周期是指用户在浏览器访问网页时,Django 根据网址在路由列表里查找相应的路由,再从路由里找到视图函数或视图类进行处理,将处理结果作为响应内容返回浏览器并生成网页内容。这个生命周期是不可逆的,而在视图里使用路由这一过程被称为反向解析。
Django 的反向解析主要由函数 reverse 和 resolve 实现:函数 reverse 是通过路由命名或可调用视图对象来生成路由地址的;函数 resolve 是通过路由地址来获取路由对象信息的。
def time(request,year,month,day):
args = ['2019','12','12']
result = resolve(reverse('index:date',args=args))
print(result.kwargs)
print(result.url_name)
print(result.namespace)
print(result.app_name)
print(result.view_name)
return HttpResponse(str(year)+'/'+str(month)+'/'+str(day))
def index(request):
kwargs = {'year':2010,'month':2,'day':10}
args = ['2019','12','12']
print(reverse('index:date',args=args))
print(reverse('index:date',kwargs=kwargs))
return HttpResponse(reverse('index:date',args=args))
首先来分析 reverse 和 resolve 这两个函数的参数。
reverse:
- viewname:代表路由命名或可调用的视图对象,一般情况下是以路由命名来生成路由地址的。
- urlconf:设置反向解析的 URLconf 模块。默认情况下,使用配置文件的 ROOT_URLCONF 属性。
- args:以列表的方式传递路由地址变量,列表元素顺序和数量应与路由地址变量的顺序和数量一致。
- kwargs:以字典方式传递路由地址变量,字典的键对应路由地址变量名,字典的键值对数量与变量的数量一致。
- current_app:提示当前正在执行的视图所在的项目应用,主要起到提示作用,在功能上并无实质作用。
一般情况下,只需设置函数的 reverse 的参数 viewname 即可,如果路由地址设有变量,那么可自行选择参数 args 或者 kwargs 设置路由地址的变量值。参数 args 和 kwargs 不能同时设置,否则会提示报错ValueError 信息。
resolve:
- path:代表路由地址,通过路由地址来获取对应的路由对象信息。
- urlconf:设置反向解析 URLconf 模块,默认情况下,使用配置文件的 ROOT_URLCONF 属性。
函数 resolve 是以路由对象作为返回值的,该对象内置多种函数方法来获取具体的路由信息。
内置的函数方法
函数方法 | 说明 |
---|---|
func | 路由的视图函数对象或视图类对象 |
args | 以列表格式获取路由的变量信息 |
kwargs | 以字典格式获取路由的变量信息 |
url_name | 获取路由命名 name |
app_name | 获取路由函数 include 的参数 arg 的第二个元素值(这里设置的一般都是APP的名字) |
app_names | 与 app_name 功能一致 |
namespace | 获取路由的命名空间 namespace |
namespaces | 与 namespace 功能一致,但以列表格式表示 |
view_name | 获取整个路由的名称,包括命名空间 |
3.3.3 路由重定向
重定向称为 HTTP 协议重定向,也可以称为网页跳转,它对应的 HTTP 状态码为 301、302、303、307、308。简单来说,网页重定向就是在浏览器访问某个网页的时候,这个网页不提供响应内容,而是自动跳转到其他网址,由其他网址来生成响应内容。
Django 的网页重定向有两种方式,第一种方式是路由重定向;第二种方式是自定义视图的重定向。两种重定向方式各有优点,前者是使用 Django 内置的视图类 ResponseView 实现的,默认支持HTTP 的 GET 请求;后者是在自定义视图的响应状态设置重定向,能让开发者实现多方面的开发要求。
RedirectView:
path('turnTo',RedirectView.as_view(url='/'),name='turnTo')
redirect:
return redirect(reverse('index:date',args=args)) # 重定向到时间函数,reverse 返回一个路由地址
本章小结
路由称为 URL(统一资源定位符),也可以称为 URLconf,是对可以从互联网上得到的资源位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的路由,用于指出网站文件的路径位置。简单地说,路由可视为我们常说的网址,每个网址代表不同的网页。
路由基本编写规则如下:
-
from django.contrib import anmin:导入内置的Admin功能模块。
-
from django.urls import path,include:导入Django的路由功能模块
-
urlpatterns:代表整个项目的路由集合,以列表的格式表示。
-
......
路由的正则表达式是由路由函数 re_path 定义的,其作用是对路由变量进行截取与判断,正则表达式是以小括号为单位的,每个小括号的前后可以使用斜杆或者其他字符将其分隔与结束。
命名空间 namespace 可以为我们快速定位某个项目应用的 urls.py,在结合路由命名 name 就能快速地从项目应用的 urls.py 找到某条路由的具体信息,这样就能有效管理整个项目的路由列表。
Django 的路由命名 name 是对路由进行命名,其作用是在开发过程中可以在视图或模版等其他功能里使用路由命名 name 来生成路由地址。
Django 的反向解析主要由函数 reverse 和 resolve 实现,函数 reverse 是通过路由命名或可调用视图对象来生成路由地址的;函数 resolve 是通过路由地址来获取路由对象信息的。
Django 的网页重定向由两种方式......