02 Django 路由 Router
在实际开发过程中,一个 Django 项目会包含很多个 app,这时候如果我们只有主路由中进行配置就会显得杂乱无章,所以通常会在每个 app 中创建各自的 urls.py 路由模块,然后从根路由出发,将 app 所属的 url 请求全部转发到相应的 urls.py 模块中。这个从主路由转发到各个应用路由的过程叫做路由的分发。
1. 路由匹配
2. 带参数路由
传单个参数,path("userdetail/<int:uid>/", user_detail),此处 <int:uid> 中的 int 是指其后 uid 参数的数据类型,一般可以是 int ,可以是 str,不可以是其他类型。
使用 127.0.0.1:8000/user/userdetail/2/ 的方式访问。
在模板中用如下方式使用
{% for user in users %}
<li>
<a href="{% url ""%}">
{{ user.name}} - {{user.age}}
</a>
</li>
{% endfor%}
传多个参数,path("userab/<int:a>/<int:b>/", user_ab_view),三个参数 path("userabc/<int:a>/<int:b>/<int:c>/", user_abc_view) ... ...
案例: 传两个参数,a = 2 和 b = 4,页面显示 a: 2 - b: 4。
在应用的 urls.py 添加子路由,path("userab/", user_ab_viwe)
在应用的 views.py 添加如下视图函数
def user_ab_view(request, a, b):
return HttpResponse(f"a: {a} - b: {b}")
使用 127.0.0.1:8000/user/userab/2/4/ 访问,根据 def user_ab_view(request, a, b),2 传给 a,4 传给 b, 页面显示 a: 2 - b: 4
使用 127.0.0.1:8000/user/userab/4/2/ 访问,根据 def user_ab_view(request, a, b),4 传给 a, 2 传给 b,页面显示 a: 4 - b: 2
此处参数为位置参数,传参方式为按位置传递。
2. 命名空间
反向解析时,解决不同 App 之间,存在相同子路由的问题。同一个 App 中的子路由,定义在一个命名空间中。即便不同 App 之间的子路由相同,但因为命名空间不同也可以找到一个确定的路由。
比如:1 班的 张伟 和 2 班的 张伟。1、2 班就是命名空间。
namespace 关键字参数指定命令空间。在项目根目录中的 urls.py 中添加带命名空间的主路由:path("user/", include(("App.urls", "App"), namespace="App")),include 有两个参数。前一个参数是一个元组(("App.urls", "App")),元组的第一个元素指向应用(App)的 urls.py 文件,第二个元素是命名空间名称(就是 include 的每二个参数的值);后一个参数就是命名空间的名称。
name 关键字参数指定子路由的名称。应用的 urls.py 中 添加带 name 关键字的子路由:path("userdetail/", user_detail, name="userdetail")
之后,可以用 命名空间:子路由名称 的方式定位视图函数,即反向解析。
一个 App 的命名空间在主路由中定义后,该 App 的每个子路由需要添加 name 关键字参数。
3. 反向解析
正常情况下,根据 URL 链接找到模板或视图中的视图函数。
在模板或视图中找到正确的 URL 链接,称为反向解析。
模板中的反向解析
正常路由:<a href="/user/userlist/"> 路由方式 </a>
反向解析:<a href="{% url "userlist" %}"> 反向解析方式 </a>
带命名空间的反向解析:<a href="{% url "App:userlist" %}"> 带命名空间的反向解析方式 </a>
带参数、带命名空间的反向解析:<a href={% url "App:userlist" user.id %}>带参数、带命名空间的反向解析方式</a>
视图中的反向解析
在视图中,重定向时需要反向解析。
重定向:跳转到某个链接时,直接再一次跳转到直定的链接。
案例:127.0.0.1:8000/user/my_redirect 重定向到百度
my_redirect 路由的视图函数如下:
from django.shortcuts import redirect
from django.http import *
from App.models import *
def my_redirect(request):
return redirect("https://www.baidu.com") # 重定向到
重定向需要从 django.shortcuts 包中导入 redirect 函数
视图中的反向解析是从一个视图函数跳转到另一个视图函数。
案例:127.0.0.1:8000/user/my_redirect 重定向到 userdetail。
my_redirect 路由的视图函数如下:
from django.shortcuts import redirect, reverse
from App.models import *
def my_redirect(request):
# return redirect(reverse("App:userdetail", args=(1,))) # 1
return redirect(reverse("App:userdetail", kwargs={"uid": 2})) # 2
反向解析函数 reverse 有两个参数。第一个参数是字符串类型,指向目标视图函数的路由,可以直接写路由(/user/detail/),也可以用命名空间(App:userdetail);第二个参数是跳转到指定路由(第一个参数)时需要的所有参数。
reverse 第二个参数的写法有两种,对应两种传参数式。
第一种方式是转位置参数,写法是 args=(1,),这种方式 args 接收一个元组,该元组的元素为路由的所有参数,因为是位置参数,所以位置一一对应,如上述代码中的 # 1。
第二种方式是关键字参数,写法是 kwargs={"uid": 2},这种方式 kwargs 接收一个字典,该字典中的内容为路由的所有参数,因为是关键字参数,所以位置可以不一一对应,但关键字一定得写正确,如上述代码中的 # 2。
视图中的反向解析需要从 django.shortcuts 包中导入 reverse 函数