Django中路由的名称空间和反向解析,reverse ,reverse_lazy 等反向解析函数的用法,以及路由命名空间和反向解析传参的解析,用例。
项目结构:
1. 路由的基础命名(不附带命名空间)
在对于单个App进行路由定义的时候,可能一个urls.py文件的定义就足够了我们的使用,但是对于多个App,我们可能通过 include方法,生成了多个子路由,通过每个App内单独的urls.py进行二次管理,所以此时,我们可以对路由进行命名,方便于我们对路由的快速调用。
通过path(name参数)我们可以快捷的路由进行命名。
项目主文件夹/urls.py
from django.urls import path,include
urlpatterns = [
path("user/", include('user.urls')), # 路由分发到user.urls中
]
user/urls.py
from django.urls import path, include,re_path
import user.views
urlpatterns = [
path("userlist/", user.views.user_list, name='userlist'), # 设置name为userlist
re_path(r"userdetail/(?P<uid>\d*)", user.views.user_detail, name='userdetail'), # 设置name为userdetail
]
此时我们通过name的设置,已经让路由有了更加简单的"别名",我们可以方便的使用"别名"去获取他的Url值。
2. 反向解析基础
2.1 通过Python方法进行反向解析
反向解析:顾名思义,通过别名,解析出来Url的原值
反向解析的用途
eg: 现在有很多很多个路由,几百个不同的路由,我们在访问其中一个路由的时候,需要让他跳转到另一个路由,那几百个路由那么复杂,我们不可能快读的找到对应的链接值,但是我们可以通过起的别名,反向解析出来URL,便于我们使用。
在Django中的反向解析一般有这几种:
- reverse 方法反向解析
- reverse_lazy 方法反向解析
- resolve_url 方法反向解析
- redirect 反向解析并重定向
- Django-HTML模板语法中反向解析动态生成Url
# 在1.路由的基础命名中,我们定义了 user/userlist/ 的 name = 'userlist'
# 此时我们便可以通过调用reverse /reverse_lazy /resolve_url 传入"userlist" 获取到user/userlist/的值
#################
view.py
#################
from django.shortcuts import render, reverse, redirect,resolve_url # 导入包
from django.urls import reverse_lazy # reverse_lazy只在django.urls中存在,但是reverse, resolve_url在shortcuts和urls中都存在
def user_list(request):
user_list = User.objects.all()
return render(request, 'user_list.html', {"user_list": user_list})
def user_detail(request, uid):
print(request.resolver_match.namespace)
-> userdetail
# request.resolver_match.namespace 用于获取当前访问的路由的名称空间
print(reverse('userlist', )) # 获取 别名=userlist的原URL
-> /user/userlist/
print(reverse_lazy('userlist')) # reverse_lazy返回与reverse一样(一般在类视图使用,见后续解释)
-> /user/userlist/
print(resolve_url("userlist")) # resolve_url 不仅仅能返回 别名对应的Url
-> /user/userlist/
print(resolve_url(user_list)) # 还可以通过传入视图方法/视图类进行返回
-> /user/userlist/
if not uid:
return redirect('userlist') # 重定向到 别名userlist对应的路由
user_info = User.objects.get(pk=uid)
return render(request, "user_detail.html", {"user_info": user_info})
但是,要注意,当前对Url进行的别名命名,其实都是 全局范围 生效的命名
也就是说,例如你在App1中定义了userlist这个链接,你就不能在App2中再起userlist,不然就会造成冲突!
所以这里我们需要引出命名空间的概念
3. 路由命名空间
上面的路由基础命名,使用的名称空间都是全局的,这就导致了,我们不同App中不能够使用相同的名称
而Django为了方便区分,于是在命名的基础上,增加了命名空间的相关参数
项目主文件夹/ urls.py
# 命名空间主要针对于上层的命名重复问题,所以首先我们修改 项目主文件夹/ urls.py
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path("admin/", admin.site.urls),
path("user/", include('user.urls',namespace='user')),
# 设置user/域名下的所有的路由的命名名称空间都在user空间中
]
user/urls.py (App下的urls)
from django.urls import path, include,re_path
import user.views
app_name = 'user' # 设置该urls的名称空间为user,此时下方定义的path都会在user名称空间中
urlpatterns = [
path("userlist/", user.views.user_list, name='userlist'), # 设置名称为 userlist
re_path(r"userdetail/(?P<uid>\d*)", user.views.user_detail, name='userdetail'), # 设置名称为userdetail
]
## 这里注意,虽然我们设置了名称为userlist,但是由于userlist在user的命名空间下
## 所以在实际调用过程中,user的名称实际为: user:userlist
## 格式: [name:namespace]
views.py
from django.shortcuts import render, reverse, redirect,resolve_url
def user_detail(request, uid):
print(request.resolver_match.view_name)
-> user:userdetail
print(reverse('user:userlist', ))
-> /user/userlist/
print(reverse_lazy('user:userlist'))
-> /user/userlist/
if not uid:
print(f'重定向')
return redirect('user:userdetail',uid=2)
user_info = User.objects.get(pk=uid)
return render(request, "user_detail.html", {"user_info": user_info})
需要注意的是,当我们使用了命名空间对某个路由进行命名后,它的名字将不在全局名称空间中,所以我们命名后
可以使用user:userlist 来反向解析,但是不可以直接使用 userlist进行解析
4. 反向解析传参
4.1 函数反向解析传参
reverse,reverse_lazy ,resolve_url,redirect的反向解析都支持传参
# 例如我们定义了一个路由
re_path(r"userdetail/(?P<uid>\d*)", user.views.user_detail, name='userdetail')
# userdetail/<uid> -> uid参数将传入user.views.user_detail
# 此时我们如果反向解析到user.views.user_detail,那也需要传递参数
# 例如reverse:
reverse('user:userdetail',uid=10) # 关键字参数设置uid=10
redirect('user:userdetail',2) # 位置参数设置uid=2
redirect('user:userdetail',kwargs={"uid":2}) # kwargs传参
4.2 HTML模板语法反向解析传参
# 语法格式
## 不传参格式
{% url "Url名称空间:Url别名" %}
## 传参格式
{% url "Url名称空间:Url别名" 参数1 参数2%} # 不同参数之间有空格!!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户列表</title>
</head>
<body>
<h2>用户列表</h2>
<ul>
{% for user in user_list %} // user_list由Django - ORM返回
<li>
<a href="{% url "user:userdetail" user.id %}">姓名:{{ user.name }}</a> //反向解析userdetail并传入uid参数
</li>
{% endfor %}
</ul>
</body>
</html>
5. 三种反向解析函数的区别,及用途
5.1 reverse()
- 接受一个 URL 名称作为参数,会根据该名称解析出对应的 URL,并返回解析后的 URL 字符串。
- 使用
reverse()
需要保证 Django 的 URL 配置已经加载,并且解析过程能够找到对应的 URL。 - 适用于在视图函数、模板等地方进行 URL 反转。
5.2 reverse_lazy()
reverse_lazy()
是 Django 的一个实用函数,类似于reverse()
,但它返回的是一个延迟解析的对象。- 它接受一个 URL 名称作为参数,会根据该名称延迟解析出对应的 URL,并返回一个代理对象。
reverse_lazy()
不会在初始化阶段尝试解析 URL,只有在实际访问代理对象时,才会触发 URL 解析。- 适用于在类视图等场景下,保证在实际访问视图时才会解析 URL,避免在启动时可能发生的错误。
- 说白了,类视图把reverse换成这个,函数视图开发种,用reverse()就可以。
5.3 resolve_url()
- 可以根据多种类型的参数进行解析,包括 URL 字符串、URL 名称、视图函数、类视图、对象的
get_absolute_url()
方法等。 - 适用于在视图中构建动态链接、进行重定向等场景。
触发 URL 解析。** - 适用于在类视图等场景下,保证在实际访问视图时才会解析 URL,避免在启动时可能发生的错误。
- 说白了,类视图把reverse换成这个,函数视图开发种,用reverse()就可以。
5.3 resolve_url()
- 可以根据多种类型的参数进行解析,包括 URL 字符串、URL 名称、视图函数、类视图、对象的
get_absolute_url()
方法等。 - 适用于在视图中构建动态链接、进行重定向等场景。
- resolve_url不光可以解析字符串,例如你传一个函数,他也能给你解析出来,所以更加专业,但是一般用不到。