Router介绍
在实际开发过程中,一个Django项目会包含很多的app,这时候如果我们只在主路由里进行配置就会显得杂乱无章,所以通常会在每个app里,创建各自的urls.py路由模块,然后从根路由出发,将app所属的url请求,全部转发到相应的us.py模块中。而这个从主路由转发到各个应用路由的过程叫做路由的分发
路由匹配
# 使用ur1给视图函数传参数
path('index/',index)
path('detail/<int:id>/',detail)
# 给ur1取别名,那么在使用此ur1的地方可以使用别名。比如:
path('index/',index,name='index')
path('detail/<int:id>/',detail,name='detail')
命名空间
在实际应用中,Django中可能存在多个应用程序,每个应用程序都可能有自己的路由模块。为了防止路由冲突,Django提供了命名空间(namespace)的概念。命名空间是一种将路由命名为层次结构的方式,使得在查询路由时可以限定在该命名空间内。
# 在根路由中可以设置命名空间
path('app/',include(('App.urls',"App"),namespace='App'))
反向解析
Django路由反向解析是一个非常重要的功能,它可以让我们在代码中使用路由别名替代URL路径,在修改URL时避免代码中的硬编码依赖,同时也可以提高可读性和可维护性。
为什么叫反向解析呢? 正常的路由匹配,都是通过path路由规则一步一步找到.html文件。而反向解析因为有路由别名的原因,是直接从.html文件找到路由规则的
# 在视图函数中,反向解析ur1:
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中:
{% ur1 'App:index' %}
路由使用
创建名App的应用
App/models.py
from django.db import models
# Create your models here.
class UserModels(models.Model):
name=models.CharField(max_length=30)
age=models.PositiveIntegerField() # 非负数
App/urls.py
from django.urls import path
from App.views import *
urlpatterns=[
# 首页
path('index/',index)
]
urls.py
from django.contrib import admin
from django.urls import path,include
from App.views import *
urlpatterns = [
# 1、直接使用根路由
path('user/',index),
# 2、使用子路由,使用include
path('user/',include('App.urls')),
# 3、使用子路由,使用include,命名空间namespace
# 使用命名空间时注意,include函数有两个参数,默认第二个参数namespace为None
# 当传命名空间的时候,第一个参数要是元组类型的,并且要加上App的名字,一般和应用的名字一样
path('user/',include(('App.urls','App'),namespace='App')),
path('admin/', admin.site.urls),
]
页面跳转
- 当路由规则使用了命名空间,反向解析也只能使用带命名空间的方式
创建userlist.html,使用index.html进行后端跳转
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h2>首页</h2>
<hr>
{# 1、URL路径 #}
{# 当访问这个路径/user/userlist 相当于会访问后端的视图函数userlist(),来到urls.py文件对userlist的路由规则 #}
<a href="/user/userlist">url路由的方式:进入用户列表页面</a>
<hr>
{# 2、反向解析 #}
{# userlist 是path路由的name值 #}
<a href="{% url 'userlist' %}">反向解析的方式:进入用户列表页面</a>
<hr>
{# 反向解析:带命名空间 #}
<a href="{% url 'App:userlist' %}">反向解析带命名空间的方式:进入用户列表页面</a>
</body>
</html>
views.py添加
# 用户列表
def usr_list(request):
users=UserModels.objects.all()
return render(request,'user_list.html',{'users':users})
路由传参
单个参数
创建userdetail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户详情</title>
</head>
<body>
<h2>用户详情</h2>
<hr>
用户姓名:{{ user.name }}
<hr>
用户年龄:{{ user.age }}
</body>
</html>
修改user_list.html
<a href="{% url 'userdetail' user.id %}">
通过用户id拼接从而,当通过反向解析跳转到path匹配路径时,会将user.id 传入路由
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户列表</title>
</head>
<body>
<h2>用户列表</h2>
<hr>
<ul>
{% for user in users %}
<li>
<a href="{% url 'userdetail' user.id %}">
{{ user.name }}-{{ user.age }}
</a>
</li>
{% endfor %}
</ul>
</body>
</html>
views.py添加
# 用户详情
def user_detail(request,uid):
print('uid:',uid)
# 通过主键获取一个对象的值
user=UserModels.objects.get(pk=uid) # pk: primary key 主键
return render(request,'userdetail.html',{'user':user})
usrls.py
from django.urls import path
from App.views import *
urlpatterns=[
# 首页
path('index/',index),
# 用户列表
path('userlist/',usr_list,name='userlist'),
# 用户详情
path('userdetail/<int:uid>/',user_detail,name='userdetail'),
]
多个参数
- 要和路由中的参数名一致,名字对应赋值,理解为关键字传值
views.py添加
# 多个参数
def user_ab_viem(request,a,b):
return HttpResponse(f'a:{a}-b:{b}')
# 要和路由中的参数名一致,名字对应赋值
def user_ba_viem(request,b,a):
return HttpResponse(f'a:{a}-b:{b}')
urls.py
from django.urls import path
from App.views import *
urlpatterns=[
# 首页
path('index/',index),
path('userlist/',usr_list,name='userlist'),
path('userdetail/<int:uid>/',user_detail,name='userdetail'),
path('userab/<int:a>/<int:b>/',user_ab_viem,name='userab'),
path('userba/<int:a>/<int:b>/',user_ab_viem,name='userba'),
]
重定向,反向解析
- 当我们需要访问这个页面让他跳转到别的页面时就需要使用重定向了,而重定向一般会用到反向解析,上面提到了在模板html文件如何使用,现在是.py文件
- 重定向函数redirect(),反向解析函数reverse(),就是通过路由别名反向得到路由
- 如下,userlist为path(‘userlist/’,user_list,name=‘userlist’),路由规则别名
- reverse(‘userlist’) => ‘/user/userlist/’
- redirect(reverse(‘userlist’)) => redirect(‘/user/userlist/’)
# 重定向
def my_redirect(request):
# 不带参数,没有使用reverse()函数反向解析
# return redirect('https://www.baidu.com')
# return redirect('/user/userlist/')
# return redirect(reverse('userlist'))
# return redirect('/user/userdetail/2/')
# 反向解析
# reverse('App:userdetail', args=(1,)) = 'userdetail/1/'
# 带命名空间的写法
# return redirect(reverse('App:userdetail',args=[3,])) # 位置参数传参,args类型可以是元组、数组
# return redirect(reverse('App:userdetail',kwargs={'uid':2})) # 关键字传参,kwargs类型为字典
# 不带命名空间
return redirect(reverse('userdetail',args=(1,))) # 位置参数传参
拓展
# 如果用了命名空间,后面的反向解析(包括视图函数和模板中)都要使用命名空间
path('user/',include(('App.urls','App'),namespace='App')),
- 也可以两个都使用
# 2、使用子路由,使用include
path('user/',include('App.urls')),
# 3、使用子路由,使用include,命名空间namespace
# 使用命名空间时注意,include函数有两个参数,默认第二个参数namespace为None
# 当传命名空间的时候,第一个参数要是元组类型的,并且要加上App的名字,一般和应用的名字一样
# 如果用了命名空间,后面的反向解析(包括视图函数和模板中)都要使用命名空间
path('user/',include(('App.urls','App'),namespace='App')),
- 这样就不会有,反向解析找不到函数的错误了