二、Django路由Router
在实际开发过程中,一个Django 项目会包含很多的 app ,这时候如果我们只在主路由里进行配置就会显得杂乱无章,所以通常会在每个 app 里,创建各自的urls.py路由模块
,然后从根路由出发,将 app 所属的 url 请求,全部转发到相应的 urls.py 模块中。而这个从主路由转发到各个应用路由的过程叫做路由的分发
re_path正则路由的写法
python
# re_path正则写法 ()表示正则分组为一个参数 (?P<参数名>regex)
re_path(r'^user_view_ab/(?P<a>\d+)/(?P<b>\d+)/$', user_view_ab, name="user_view_ab")
这样就是匹配user_view_ab/1/2
等数字参数
路由匹配
python
# 使用url给视图函数传参数
path('index/', index)
path('detail/<int:id>/', detail)
# 给url取别名,那么在使用此url的地方(例如页面模板反向解析)可以使用别名。比如:
path('index/',index,name='index')
path('detail/<int:id>/', detail, name='detail')
根据路由的name属性,获取路由url
reverse('index') => 路由'index/'
反向解析
Django路由反向解析
是一个非常重要的功能,它可以让我们在代码中使用路由别名替代URL路径,在修改URL时避免代码中的硬编码依赖,同时也可以提高可读性和可维护性。
python
# 在视图函数中,反向解析url:
from django.shortcuts import render,redirect,reverse
def buy(request):
return redirect(reverse('index'))
return redirect(reverse('detail',args=[2]))
return redirect(reverse('detail',kwargs={"id":2}))
#在templates中,使用别名:
{% url 'detail' stu.id %}
# 使用命名空间:
# 指定命令空间后,使用反向解析时需要加上命名空间,比如:
# 1.在视图函数中:
return redirect(reverse('App:index'))
# 2.在templates中:
{% url 'App:index'%}
页面之间相互跳转(通过html)
- 在根目录下的
urls.py
添加如下代码
python
from django.contrib import admin
from django.urls import include, path
from App.views import *
urlpatterns = [
# 使用子路由:
path("user/", include("App.urls")),
# 使用子路由: 使用命名空间
path("user/", include(("App.urls","App"), namespace="App")),
path('admin/', admin.site.urls),
]
- App/urls.py子路由文件
python
from tkinter.font import names
from django.urls import path
from App.views import *
urlpatterns = [
# 首页
path('index/', index, name='index'),
# 用户列表
path('user_list/', user_list, name='user_list'),
]
- 定义
视图函数
和user_list.html
文件
python
# 用户列表
def user_list(request):
return render(request, 'user_list.html')
- 在想要添加跳转链接的页面(这里只使用后端的Django跳转方式,不使用前端超链接)添加代码
django
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Index</title>
</head>
<body>
<h2>首页</h2>
<hr />
{% comment %} url路由来跳转 {% endcomment %}
<a href="/user/user_list/">url路由跳转: 进入用户列表</a>
<hr />
{% comment %} 反向解析来跳转 {% endcomment %}
<a href="{% url 'user_list' %}">反向解析跳转: 进入用户列表</a>
user_list是路由路径的name值
url 是Django的模板,用于生成url
<hr />
{% comment %} 带命名空间的反向解析 {% endcomment %}
<a href="{% url 'App:user_list' %}">带命名空间的反向解析: 进入用户列表</a>
</body>
</html>
- url路由跳转方式: 链接路径为 127.0.0.1:8000后面的内容
- 反向解析来跳转: 反向解析就是从 html页面(点击) -> 找到路由 -> 找到视图函数(
user_list是路由路径的name值
) - 带命名空间的反向解析: 命名空间就是
根/urls.py文件include方法
中指定的namespace
,命名空间就是为了使不同的应用之间可以使用相同的子路由路径名(例如上面的user_list)
路由传参(单个参数)
在App
的子路由中新增以下路由规则
python
# 详情页 <> 号内为参数传给user_detail视图函数
path('user_detail/<int:uid>/', user_detail, name='user_detail'),
定义视图函数user_detail
python
# 用户列表
def user_list(request):
# 获取所有用户数据
users = UserModel.objects.all()
return render(request, 'user_list.html',{"users":users})
def user_detail(request,uid): # uid从路由参数中获取
# print("uid",uid)
# 获取单个用户数据
user = UserModel.objects.get(pk=uid) # pk是主键primary key
return render(request, 'user_detail.html',{"user":user}) # 传递参数到模板中
在user_list.html文件中接收
user_list传过来的users参数,遍历(利用模板语法添加li>a标签)
django
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>用户列表</title>
<style>
a {
text-decoration: none;
}
</style>
</head>
<body>
<h2>用户列表</h2>
<hr />
<ul>
{% for user in users %} {% comment %} 反向解析 {% endcomment %}
<li>
<a href="{%url 'App:user_detail' user.id%}">{{user.name}} - {{user.age}}</a>
</li>
{% endfor %}
</ul>
</body>
</html>
所以,最终生成的a标签变成了<a href="/user/user_detail/1/">张三 - 19</a>
整个过程就是按顺序发生
- 首先用户访问user/user_list.html界面,程序调用
视图函数
获取所有用户列表并传参- 在
user_list
函数中,程序渲染本地的user_list.html
返回,在渲染的过程中,将uset_list()中获取的用户列表逐个渲染成具体的链接- 这是对模板语法的解释
url
代表当前界面的url,App:user_detail
表示到根路由path("user/", include(("App.urls","App"), namespace="App"))
中在逐层(include(("App.urls","App")
,从应用App的urls.py子路由文件)找到名为user_detail
的路由项- 找到如下所示
path('user_detail/<int:uid>/', user_detail, name='user_detail')
- 然后
user.id
就是把id属性传给路由参数,相对于变成``path('user_detail/user.id/', user_detail, name='user_detail')`
路由参数支持的类型
Django支持多种类型的路由参数,常见的有:
- int :接收整数,如
<int:user_id>
。 - str :接收字符串,如
<str:username>
。 - slug :接收短横线连接的字符串,如
<slug:slug>
。 - uuid :接收UUID,如
<uuid:uuid>
。 - path :接收包含斜杠的字符串,如
<path:subpath>
。
路由传参(多参数)
视图函数
python
def user_view_ab(request,a,b):
return HttpResponse(f"a={a},b={b}")
子路由
python
# 带参数的视图函数,注意,参数的名字必须和视图函数中参数的名字一致
path("user_view_ab/<int:a>/<int:b>/", user_view_ab, name="user_view_ab")
注意!!! 参数名称要对应
重定向redirect
函数
在视图函数中,可以重定向到别的网页或者路径
python
path('user_detail/<int:a>/',user_detail,name='userdetail'),def user_detail(a):
return HttpResponse("user_detail")
# 重定向
def my_redirect(request):
return redirect('http://www.baidu.com')
def my_redirect2(request):
return redirect('/user/user_list/')
def my_redirect3(request):
# reverse反向解析(根据路由name属性找到对应url)
return redirect(reverse('user_list')) # 相当于 return redirect(/user/user_list/)
return redirect(reverse('App:userdetail', args=(1,))) # 传参给path('user_detail/<int:a>/',user_detail,name='userdetail'),args=元组或列表,kawrgs=字典
return redirect(reverse('App:userdetail', kwargs={'a':2}))
在子路由中增加重定向部分
python
# 用户列表(原有)
path('user_list/', user_list, name='user_list'),
path('user_detail/<int:a>/',user_detail,name='userdetail'),
# 重定向
path('myredirect/', my_redirect),
path('myredirect2/', my_redirect2),
path('myredirect3/', my_redirect3),