Django - 初探路由
路由定义规则
准备工作:新建项目MyDjango,新建App index,在项目的index 文件夹里新添加一个空白内容的.py 文件,命名为urls.py。项目结构如下图:
在App(index 文件夹)里添加urls.py 是将所有属于App 的路由都写入该文件中,这样更容易管理和区分每个App的路由地址,而MyDjango 文件夹的urls.py 是将每个App的 urls.py 统一管理。其工作原理如下:
(1) 运行MyDjango 项目时,Django 从 MyDjango 文件夹的urls.py 找到各个App所定义的路由信息,生成完整的路由列表
(2) 当用户在浏览器上访问某个路由地址时,Django 就会收到该用户的请求信息
(3) Django 从当前请求信息获取路由地址,并在路由列表里匹配相应的路由信息,再执行路由信息所指向的视图函数(或视图类) ,从而完成整个请求响应过程。
MyDjango 文件夹得urls.py 代码如下:
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
# 指向内置Admin后台系统的路由文件 setes.py
path('admin/', admin.site.urls),
# 指向index 的路由文件 urls.py
path('', include('index.urls')),
]
以上定义了两条路由信息,分别是Admin 站点管理 和 首页地址(index)。其中,Admin站点管理在创建项目时自动生成,一般情况下无须修改;首页地址是指index文件夹得urls.py
- path('admin/', admin.site.urls): 设定Admin得路由信息。'admin/' 代表 127.0.0.1/8001/admin得路由地址,admin.site.urls 指向内置Admin功能所自定义的路由信息
venv/Lib/site-packages/django/contrib/admin/sites.py - path('', include('index.urls')): 路由地址为"",即127.0.0.1:8001 ,通常是网站得首页。路由函数include 是将该路由信息分发给 index得urls.py处理
由于首页地址分发给index 的urls.py 处理,因此下一步需要对index 的urls.py 编写路由规则:
#index\urls.py
from django.urls import path
from index import views
urlpatterns = [
path('', views.index)
]
路由信息 path('', views.index),的views.index 是指视图函数index处理网站首页的用户请求和响应过程。
#index\views.py
from django.shortcuts import render
def index(request):
print('this is a tets')
return render(request, 'index.html')
index函数必须设置一个参数,参数名不固定,通常以request 进行命名,代表当前用户的请求对象。
请求结果:
从上述列子看到,当启动MyDjango时,Django 会从配置文件setting.py 读取属性ROOT_URLCONF 的值,默认值为MyDjango.urls,代表MyDjango 文件夹的urls.py文件,然后根据ROOT_URLCONF的值来生成整个项目的路由列表。
路由文件urls.py 的路由定义规则是相对固定的,路由列表由urlpatterns 表示,每个列表元素代表一条路由。路由是由Django 的path函数定义的,该函数的第一个参数是路由地址,第二个参数是路由所对应的处理函数(视图函数或视图类),这两个参数是路由定义的必选参数。
路由变量的设置
在日常开发中,有时一个路由可以代表多个不同的页面,如编写带有日期的路由。Django 在定义路由时,可以对路由设置变量,使路由具有多样性。
路由变量类型有字符类型、整型、slug、和uuid,最常用的类型是整型和字符类型
- 字符类型: 匹配任何非空字符串,但不含斜杠。如果没有指定类型,就默认使用该类型
- 整型: 匹配0和正整数
- slgu:可以理解为注释、后缀或附属等概念。常作为路由的解释性字符。可匹配任何ASCCI 字符以及连接符和下划线。能使路由更加清晰易懂。比如网页标题是"13 岁的孩子",其路由地址可以设置为:'13-sui-de-hai-zi'。
- uuid:匹配一个uuid格式的对象。为了防止冲突,规定必须使用'-' 并且所有字母必须小写。例如:075194d3-6885-417e-a8-a8-6c931e272d00。
根据上述类型变量,在 index 文件夹的urls.py 里新定义路由,代码如下:
from django.urls import path
from index import views
urlpatterns = [
path('<year>/<int:month>/<slug:day>', views.myvariable)
]
在路由中,使用变量符号'<>' 可以为路由设置变量。在括号里面以冒号划分为两部分,冒号前面代表的是数据类型,冒号后面代表的是变量名,变量名可以自行命名,如果没有设置,默认就是字符类型。上述代码设置了3个变变量:
: 数据格式为字符,与<str: year> 的含义一样 - <int: month>:变量为名month,数据格式为整型
- <slug: day> :变量名为day,数据格式为slug
视图函数处理请求:
# index\views.py
def myvariable(request, year, month, day):
return HttpResponse(f'{year} / {month} / {day}')
用连接访问:http://localhost:8001/2024/05/02
如果浏览器输入的路由地址与变量类型不相符,Django 就会提示Page not found:
路由设置的变量要和视图函数的参数保持一一对应。如果数量对不上,那么程序会抛出参数不相符的报错信息:
。
除了在路由变量地址设置变量外,Django 还支持在路由地址外设置变量(路由的可选变量)。我们在index 的urls.py 和 views.py 中分别新增路由和视图函数,如下:
# index\urls.py
from django.urls import path
from index import views
urlpatterns = [
path('<year>/<int:month>/<slug:day>', views.myvariable),
path('', views.index, {'msg': '2024/05/02'}),
]
# index\views.py
def index(request,msg):
return HttpResponse(f'这是路由地址之外的变量:{msg}')
以上函数可以看出,路由函数path 的第三个参数是 {'msg': '2024/05/02'},该参数的设置规则如下:
- 只能以字段的形式表示
- 设置的参数只能在视图函数中获取和使用
- 字典的一个键值对代表一个参数,参数值
- 参数值没有数据格式限制,可以为某个实例对象,字符串和列表(元组)等。
正则表达式的路由定义
为了进一步规范日期格式,可以使用正则表达式限制路由地址变量的取值范围。代码如下:
#index\urls.py
from django.urls import path,re_path
from index import views
urlpatterns = [
re_path('(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2}).html', views.mydata)
]
路由的正则表达式是由路由函数re_path 定义的,正则表达式是以小括号为单位的,每个小括号前后可以使用斜杠或者字符将其分割与结束。 在小括号内部,可分为3部分,以(?P
- ?P 是固定格式,字母P 必须大写。
为变量名 - [0-9]{4} 是正则表达式的匹配模式,代表变量的长度为4,只允许取0~9值
视图函数:
# index\views.py
def mydata(request,year, month,day):
return HttpResponse(f'{year} / {month} / {day}')
路由地址末端设置了".html",这是一种伪静态URL技术,可以将网址设置为静态网址,用于SEO 搜索引擎的爬取。
命名空间与路由命名
网站规模越大,其网页的数量就会越多,如果网站的网址过多,在管理或者维护上就会存在一定的难度。 Django 为了更好地管理和使用路由,可以为每条路由设置命名空间或路由命名
命名空间
在MyDango 项目里新建应用user,并且在user 文件夹里创建urls.py,然在在配置文件settting.py 的INSTALLED_APP 中添加应用user,使得Django 在运行的时候能够识别到项目应用user,
在MyDango 文件夹的urls.py 重新定义路由信息,分别指向index\urls.py 和 user\urls.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
# 指向内置Admin后台系统的路由文件 setes.py
path('admin/', admin.site.urls),
# 指向index 的路由文件 urls.py
path('', include(('index.urls', 'index'), namespace='index')),
# 指向user 文件夹下的 urls.py
path('user/', include(('user.urls', 'user'), namespace='user')),
]
路由函数include 设有参数arg 和 namespace,参数arg 指向项目应用App 的urls.py 文件,其数据格式以元组或字符串表示,可选参数namespac额 是路由的命名空间。
若要对路由设置参数namespace,则参数arg 必须以元组格式表示,并且元组的长度必须为2。元组的元素说明如下:
- 第一个元素为项目应用的urls.py 文件。
- 第二个元素可以自行命名,但不能为空。一般情况下是以项目应用的名称进行命名。
Django 的命名空间 可以为我们快速定位某个项目应用的urls.py,再结合路由命名name 就能快速地从项目应用的urls.py 找到某条路由的具体信息,这样就能有效管理整个项目的路由列表。
路由的使用方式
路由为网站开发定义了具体的网址,不仅如此,它还能被其他功能模块使用,比如视图、模板、模型、Admin 后台 或表单等
在模板中使用路由
# MyDjango\urls.py 配置:
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('index.urls')) # 未使用命名空间
]
# index\urls.py 配置:
urlpatterns = [
path('<year>/<int:month>/<slug:day>', views.mydate, name='mydate'), # 路由命名
path('', views.index),
]
# index\views.py 配置:
def index(request):
return render(request, 'index.html')
def mydate(request, year, month, day):
return HttpResponse(f'{year} / {month} / {day}')
模板配置:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<span>Hello World!!!</span>
<br>
<a href="{% url 'mydate' '2024' '05' '02'%}">查看日期</a>
</body>
</html>
验证:
模板使用了Django 内置的模板语法 ur 来生成路由地址,模板语法 url 里设置有4个不同的参数,其说明如下:
- mydate: 代表命名为 mydate 的路由,即index的urls.py 设有字符类型、整型和slug的路由。
- 2019 :代表路由地址变量year
- 01:代表路由地址变量 month
- 10: 代表路由地址变量day
模板语法 url 的参数设置与路由定义是相互关联的,具体说明如下:
- 若路由地址存在变量,则模板语法url需要设置相应的参数值,参数值之间使用空格隔开
- 若路由地址不存在变量,则模板语法url 只需要设置路由命名name 即可
- 若路由地址的变量与模板语法url 的参数数量不同,则在浏览器访问网页的时候会提示NoReverseMathc at 的错误信息
上述例子中,MyDjango\urls.py 在使用函数include 定义路由时并没有设置命名空间。若同时设置了命名空间namespace 和 name,则在模板里使用路由的方式有所变化。
正确使用方式为:
<a href="{% url 'index:mydate' '2024' '05' '02'%}">查看日期</a>
反向解析reverse 和 resolve
Django 的反向解析主要是由函数 reverse 和 resolve 实现:函数reverse 是通过路由命名或可调用视图对象来生成路由地址的;函数resolve 是通过路由地址来获取路由对象信息的。
案例配置信息:
# MyDjango\urls.py:
urlpatterns = [
# 指向内置Admin后台系统的路由文件 setes.py
path('admin/', admin.site.urls),
# 指向index 的路由文件 urls.py
path('', include(('index.urls', 'index'), namespace='index')),
]
# index\urls.py:
urlpatterns = [
path('<year>/<int:month>/<slug:day>', views.mydate, name='mydate'),
path('', views.index),
]
视图中代码如下:
from django.shortcuts import HttpResponse, reverse
from django.urls import resolve
def index(request):
kwargs = {'year': 2024, 'month': 2, 'day': 10}
args = ['2024', '12', '12']
# 使用reverse 生成路由地址
print(reverse('index:mydate', args=args))
print(reverse('index:mydate', kwargs=kwargs))
return HttpResponse(reverse('index:mydate', args=args))
def mydate(request, year, month, day):
args = ['2024', '05', '02']
result = resolve(reverse('index:mydate', args=args))
print('kwargs: ', result.kwargs)
print('url_name: ', result.url_name)
print('namespace: ', result.namespace)
print('view_name: ', result.view_name)
print('app_name: ', result.app_name)
return HttpResponse(f'{year}/{month}/{day}')
函数index 主要使用反向解析函数reverse 函数来生成路由mydate 的路由地址。函数参数下:
def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None):
设有不选参数viewname,其他参数是可选参数,说明如下:
- viewname:代表路由或可调用视图对象,一般情况下以路由命名name 来生成路由地址的
- urlconf:设置反向解析的URLconf 模块。默认请况下,使用配置文件setting.py 的ROOT_URLCONF 属性。
- args:以列表方式传递路由地址变量,列表元素顺序和数量应该与路由地址变量的顺序和数量一致
- kwargs: 以字典的方式传递路由地址变量,字典的键必须对应路由地址变量名,字典的键值对数量与变量的数量一致
- current_app: 提示当前正在执行的视图所在的项目应用,主要起到提示作用
在浏览器访问:locahost:8001,当前请求将有视图函数index 处理,reverse 来获取路由名为 mydate 的路由地址并显示在网页上:
控制台输出:
在浏览器访问:localhost:8001/2024/05/02 ,控制台输出:
kwargs: {'year': '2024', 'month': 5, 'day': '02'}
url_name: mydate
namespace: index
view_name: index:mydate
app_name: index
路由重定向
Django 的网页重定向有两种方式,第一种方式是理由重定向,第二种方式是自定义视图的重定向。两种重定向方式各有优点,前者是使用Django 内置的视图类 RedirectView 实现的,默认支持HTTP 的GET请求,后者是在自定义视图的响应状态设置重定向,能够让开发者实现多方面的开发需求。
案例:
# index\urls.py
from django.urls import path
from index import views
from django.views.generic import RedirectView
urlpatterns = [
path('<year>/<int:month>/<slug:day>', views.mydate, name='mydate'),
path('', views.index),
path('turnTo', RedirectView.as_view(url='/'), name='turnTo')
]
#index\views.py
from django.shortcuts import HttpResponse, reverse, redirect
from django.urls import resolve
def index(request):
args = ['2024', '05', '03']
return redirect(reverse('index:mydate', args=args))
def mydate(request, year, month, day):
return HttpResponse(f'this is mydate function,param {year}/{month}/{day}')
浏览器上输入:http://localhost:8001/turnTo,发现该网址首先通过视图类RedirectView 重定向到首页,然后再视图函数index 里使用重构定向函数redicet()跳转到路由名为 mydate 的路由地址
本文来自博客园,作者:chuangzhou,转载请注明原文链接:https://www.cnblogs.com/czzz/p/18169978