在实际开发过程中,一个Djaqgo 项目会包含很多的 app,这时候如果我们只在主路由里进行配置就会显得杂乱无章,所以通常会在每个app 里,创建各自的 urls.py 路由模块,然后从根路由出发,将 app 所属的 url 请求,全部转发到相应的 urls.py模块中。而这个从主路由转发到各个应用路由的过程叫做路由的分发。
# 使用ur1给视图函数传参数
path('index/', index)
path('detail//' , detail)
# 给ur1取别名,那么在使用此ur1的地方可以使用别名。比如:
path('index/', index, name='index')
path('detail//' , detail, name='detail')
在实际应用中,Diango中可能存在多个应用程序,每个应用程序都可能有自己的路由模块。为了防止路由冲突,Django提供了命名空间(namespace)的概念。命名空间是一种将路由命名为层次结构的方式,使得在查询路由时可以限定在该命名空间内。
# 在根路由中可以设置命名空间
path('app/', include(('App.urls',"App",namespace='App')
Django路由反向解析是一个非常重要的功能,它可以让我们在代码中使用路由别名替代URL路径,在修改URL时避免代码中的硬编码依赖,同时也可以提高可读性和可维护性。
# 在视图函数中,反向解析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中:
{% url 'App:index' %}
{% url 'App:detail' 2 %}
如果用了命名空间,后面的反向解析(包括视图函数和模板中)都要使用命名空间
新建一个新项目Day02MyDjangoPro01
App\models.py
from django.db import models
class UserModel(models.Model):
name = models.CharField(max_length=30)
age = models.PositiveIntegerField() # 非负数
生成迁移文件: python manage.py makemigrations
执行迁移: python manage.py migrate
App\urls.py
from django.urls import path
from App.views import *
urlpatterns = [
path('index/', index), # 首页
]
App\templates\index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h2>首页</h2>
<hr>
</body>
</html>
App\views.py
from django.shortcuts import render
def index(request):
return render(request, "index.html")
根路由 Day02MyDjangoPro01\urls.py
from django.contrib import admin
from django.urls import path, include
# from App.views import *
urlpatterns = [
path('admin/', admin.site.urls),
# 1. 直接使用根路由
# path('user/', index),
# 2.使用子路由: 使用include
# path('user/', include('App.urls')),
# 3.使用子路由: 使用include, 命名空间namespace
path('user/', include(('App.urls', 'App'), namespace='App')),
]
http://127.0.0.1:8000/user/index/
App\templates\user_list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户列表</title>
</head>
<body>
<h2>用户列表</h2>
<hr>
</body>
</html>
App\views.py 创建视图函数user_list
from django.shortcuts import render
# 首页
def index(request):
return render(request, "index.html")
# 用户列表
def user_list(request):
return render(request, "user_list.html")
App\urls.py 写一个路由
from django.urls import path
from App.views import *
urlpatterns = [
path('index/', index), # 首页
path('user_list/', user_list, name='user_list') # 用户列表
]
需求:在index页面跳转到user_list页面
根路由 Day02MyDjangoPro01\urls.py
反向解析 {% url '定义路由后面name的名字' %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h2>首页</h2>
<hr>
{# url路由跳转 #}
<a href="/user/user_list/">点击url路由的方式:进入用户列表的页面</a>
<br>
{# 反向解析 {% url '定义路由后面name的名字' %} #}
{# user_list 是path路由的name值 #}
<a href="{% url 'user_list' %}">反向解析的方式:进入用户列表的页面</a>
<br>
</body>
</html>
点击是可以跳转的
根路由 Day02MyDjangoPro01\urls.py
App\templates\index.html
反向解析:带命名空间 {% url '命名空间的名称:定义路由后面name的名字' %}
。namespace你可以理解为 一个子路由有一个命名空间。
这样做有什么用?一个命名空间表示一个应用,我们在写代码的时候,如果我们在不同应用中取相同name的话,那么可以通过应用空间namespace去区分他们。
如果是用子路由,就建议使用命名空间!!!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h2>首页</h2>
<hr>
{# url路由跳转 #}
<a href="/user/user_list/">点击url路由的方式:进入用户列表的页面</a>
<br>
{# 反向解析 {% url '定义路由后面name的名字' %} #}
{# user_list 是path路由的name值 #}
{# 反向解析的方式:进入用户列表的页面#}
<br>
{# 反向解析:带命名空间 {% url '命名空间的名称:定义路由后面name的名字' %} #}
<a href="{% url 'App:user_list' %}">反向解析带命名空间的方式:进入用户列表的页面</a>
</body>
</html>
点击是可以跳转的
App\views.py ,user_list 传参、用户详情
from django.shortcuts import render
from App.models import *
# 首页
def index(request):
return render(request, "index.html")
# 用户列表
def user_list(request):
# 获取所有用户数据
users = UserModel.objects.all()
return render(request, "user_list.html", {"users": users})
# 用户详情
def user_detail(request, uid):
# print("uid:", uid)
user = UserModel.objects.get(pk=uid) # pk:primary key主键
return render(request, "user_detail.html", {'user': user})
增加一个页面,用户详情页面, App\templates\user_detail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户详情</title>
</head>
<body>
<h2>用户详情</h2>
<hr>
<p>用户的名字:{{ user.name }}</p>
<p>用户年龄:{{ user.age }}</p>
</body>
</html>
添加路由 App\urls.py
from django.urls import path
from App.views import *
urlpatterns = [
path('index/', index), # 首页
path('user_list/', user_list, name='user_list'), # 用户列表
path('userdetail//' , user_detail, name='userdetail'), # 用户详情
]
App\templates\user_list.html ,将数据显示
<!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 'App:userdetail' user.id %}">{{ user.name }} - {{ user.age }}</a>
</li>
{% endfor %}
</ul>
</body>
</html>
App\views.py
from django.http import HttpResponse
# 多个参数
def user_ab_view(request, a, b):
return HttpResponse(f'a:{a} - b:{b}')
添加路由 App\urls.py
# 多个参数
path('userab///' , user_ab_view, name='user_ab'),
但是如果我把视图函数参数顺序反过来 会怎么样呢?
可以看到跟视图函数a,b顺序是没有关系的,a传给a,b传给b。
我们在用的时候,要和路由中的参数名一致,名字对应赋值
,你可以理解为相当于关键字参数传值,a赋给a,b赋给b。
re 是正则的意思
第一个参数 得用正则,一般前面加一个r,字符串转义,这个跟正则没有太大关系,一般会写上r。有几个参数写上几个括号() ,整个字符串'user_ba/()/()/'
会当做字符去处理的,
\d
表示一个数字,\d+
表示它可以是数字,表示这一块接收的是整数,+
的意思就是一个整数多个整数都可以,但不能为零个整数。
a表示整数的名字,?P
这一串其实是给它命一个名字,给这个分组命名为a。
App\views.py
from django.shortcuts import render, redirect, reverse
# 重定向
def my_redirect(request):
return redirect("https://blog.csdn.net/weixin_59633478/category_12401835.html")
添加路由 App\urls.py
path("myredirect/", my_redirect)
打开浏览器,输入http://127.0.0.1:8000/user/myredirect
注意
:自动跳到了https://blog.csdn.net/weixin_59633478/category_12401835.html,地址改变了
App\views.py
def my_redirect(request):
# return redirect("/user/user_list")
return redirect("/user/userdetail/2/") # 带参数:第一种写法
def my_redirect(request):
# return redirect("/user/userdetail/2/") # 带参数:第一种写法
# 反向解析
return redirect(reverse("App:userdetail", args=(2,)))
# reverse("App:userdetail", args=(2,)) 相当于 '/user/userdetail/2/'
注意: 有命名空间一定要写命名空间,如果没有命名空间就不用写命名空间
# 不带命名空间
return redirect(reverse("userdetail", args=(2,)))
def my_redirect(request):
# 反向解析
# return redirect(reverse("App:userdetail", args=(2,)))
# 反向解析: 关键字传参
return redirect(reverse("App:userdetail", kwargs={'uid': 2}))