Django路由层

一、路由的作用

路由即请求地址与视图函数的映射关系,如果把网站比喻为一本书,那路由就好比是这本书的目录,在Django中路由默认配置在urls.py中,如下图:

urls.py

from django.urls import re_path

由一条条映射关系组成的urlpatterns这个列表称之为路由表

urlpatterns = [

re_path(regex, view, kwargs=None, name=None),

]

re_path参数介绍

1、regex:正则表达式,专门用来匹配url地址(url地址中所有内容均被当作字符串)的路径部分,不考虑请求方法如GET、POST或者域名,例如:

请求url地址为:https://www.example.com/myapp/,,正则表达式要匹配的部分是myapp/

请求url地址为: https://www.example.com/myapp/?page=3, 正则表达式要匹配的部分是myapp/

注意:

1.1 django的url配置不会考虑请求方法,换句话说,对于相同的URL地址,所有的请求方法如POST、GET、HEAD等,都将被路由到相同的功能view上

1.2 切记正则表达式开头无需加/

2、view:通常为一个视图函数,用来处理业务逻辑

3、kwargs:额外传递给视图函数的参数,可选(用法详见第三小节:分组)

4、name:为正则表达式匹配到的url地址起别名,可选(用法详见第五小节:反向解析)

案例:

urls.py文件

python 复制代码
from django.contrib import admin
from django.urls import path, re_path # 导入re_path,关于path的使用我们在本章最后一小节介绍
from app01 import views # 导入模块views.py

urlpatterns = [
    path('admin/', admin.site.urls), # 由django自动生成该行代码,本质与re_path一样都只是一条匹配规则而已,只不过该规则的实现由django框架提供(对应的视图为admin.site.urls),在没有正式介绍该行代码作用之前,忽略即可,暂时注释掉也可以
    
    re_path(r'^index/$',views.index), # 新增一条
]

views.py文件
from django.shortcuts import render
from django.shortcuts import HttpResponse # 导入HttpResponse,用来生成响应信息

# 新增视图函数index
def index(request):
    return HttpResponse('index page...')
测试:
python manage.py runserver 8001 # 在浏览器输入:http://127.0.0.1:8001/index/ 会看到 index page...

三、分组

什么是分组、为何要分组呢?比如我们开发了一个博客系统,当我们需要根据文章的id查看指定文章时,浏览器在发送请求时需要向后台传递参数(文章的id号),可以使用 http://127.0.0.1:8001/article/?id=3,也可以直接将参数放到路径中http://127.0.0.1:8001/article/3/

针对后一种方式Django就需要直接从路径中取出参数,这就用到了正则表达式的分组功能了,分组分为两种:普通分组与命名分组

普通分组

python 复制代码
urls.py文件
from django.contrib import admin
from django.urls import path,re_path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    
    # 下述正则表达式会匹配url地址的路径部分为:article/数字/,匹配成功的分组部分会以位置参数的形式传给视图函数,有几个分组就传几个位置参数
    re_path(r'^article/(\d+)/$',views.article), 
]
views.py文件
from django.shortcuts import render
from django.shortcuts import HttpResponse

# 需要额外增加一个形参用于接收传递过来的分组数据
def article(request,article_id):
    return HttpResponse('id为 %s 的文章内容...' %article_id)
测试:
python manage.py runserver 8001 # 在浏览器输入:http://127.0.0.1:8001/article/3/ 会看到: id为 3 的文章内容...

命名分组

当我们对分组命名后,就会按照key=value的关键字参数形式为视图函数传参

urls.py文件

python 复制代码
from django.contrib import admin
from django.urls import path,re_path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    
    # 该正则会匹配url地址的路径部分为:article/数字/,匹配成功的分组部分会以关键字参数(article_id=匹配成功的数字)的形式传给视图函数,有几个有名分组就会传几个关键字参数,需要强调一点是:视图函数得到的值均为字符串类型
    re_path(r'^article/(?P<article_id>\d+)/$',views.article), 
]

views.py文件

python 复制代码
from django.shortcuts import render
from django.shortcuts import HttpResponse

# 需要额外增加一个形参,形参名必须为article_id
def article(request,article_id):
    return HttpResponse('id为 %s 的文章内容...' %article_id)

python manage.py runserver 8001 # 在浏览器输入:http://127.0.0.1:8001/article/3/ 会看到: id为 3 的文章内容...

总结

普通分组和命名分组都是为了获取路径中的参数,并传递给视图函数,区别在于普通分组是以位置参数的形式传递,命名分组是以关键字参数的形式传递。

强调

普通分组和有名分组不要混合使用

指定默认值

python 复制代码
# urls.py中
from django.urls import re_path 
from app01 import views

urlpatterns = [
    re_path(r'^article/$', views.article), # 第一条
    re_path(r'^article/(?P<article_id>\d+)/$',views.article), # 第二条
]

# views.py中,可以为num指定默认值
from django.shortcuts import HttpResponse

def article(request, article_id="1"):
    return HttpResponse('id为 %s 的文章内容...' %article_id)

为视图函数article指定默认参数article_id="1"后,urlpattrens中的两条匹配规则就可以共用一个视图函数了,具体分析如下:
当url为:http://127.0.0.1:8080/article/时,匹配成功第一条
当url为:http://127.0.0.1:8080/article/111/时,匹配成功第二条

四、路由分发

随着项目功能的增加,app会越来越多,路由也越来越多,每个app都会有属于自己的路由,如果再将所有的路由都放到一张路由表中,会导致结构不清晰,不便于管理,所以我们应该将app自己的路由交由自己管理,然后在总路由表中做分发,具体做法如下

1 创建两个app

python 复制代码
# 新建项目mystie2
E:\git>django-admin startproject mysite2
# 切换到项目目录下
E:\git>cd mysite2
# 创建app01和app02
E:\git\mysite2>python3 manage.py startapp app01
E:\git\mysite2>python3 manage.py startapp app02

2在每个app下手动创建urls.py来存放自己的路由,如下:

app01下的urls.py文件

python 复制代码
from django.urls import re_path
# 导入app01的views
from app01 import views

urlpatterns = [
    re_path(r'^index/$',views.index), 
]

app01下的views.py

python 复制代码
from django.shortcuts import render
from django.shortcuts import HttpResponse

def index(request):
    return HttpResponse('我是app01的index页面...')

app02下的urls.py文件

python 复制代码
from django.urls import re_path
# 导入app02的views
from app02 import views

urlpatterns = [
    re_path(r'^index/$',views.index), 
]

app02下的views.py

python 复制代码
from django.shortcuts import render
from django.shortcuts import HttpResponse

def index(request):
    return HttpResponse('我是app02的index页面...')

3 在总的urls.py文件中(mysite2文件夹下的urls.py

python 复制代码
from django.contrib import admin
from django.urls import path,re_path,include

# 总路由表
urlpatterns = [
    path('admin/', admin.site.urls),
    
    # 新增两条路由,注意不能以$结尾
    # include函数就是做分发操作的,当在浏览器输入http://127.0.0.1:8001/app01/index/时,会先进入到总路由表中进行匹配,正则表达式r'^app01/'会先匹配成功路径app01/,然后include功能会去app01下的urls.py中继续匹配剩余的路径部分
    re_path(r'^app01/', include('app01.urls')),
    re_path(r'^app02/', include('app02.urls')),
]

测试:

python 复制代码
python manage.py runserver 8001  
# 在浏览器输入:http://127.0.0.1:8001/app01/index/ 会看到:我是app01的index页面...
# 在浏览器输入:http://127.0.0.1:8001/app02/index/ 会看到:我是app02的index页面...

五、反向解析

在软件开发初期,url地址的路径设计可能并不完美,后期需要进行调整,如果项目中很多地方使用了该路径,一旦该路径发生变化,就意味着所有使用该路径的地方都需要进行修改,这是一个非常繁琐的操作。

解决方案就是在编写一条re_path(regex, view, kwargs=None, name=None)时,可以通过参数name为url地址的路径部分起一个别名,项目中就可以通过别名来获取这个路径。以后无论路径如何变化别名与路径始终保持一致。

上述方案中通过别名获取路径的过程称为反向解析

案例:登录成功跳转到index.html页面

在urls.py文件中

python 复制代码
from django.contrib import admin
from django.urls import path,re_path
from app01 import views
urlpatterns = [
    path('admin/', admin.site.urls),
    
    re_path(r'^login/$', views.login,name='login_page'), # 路径login/的别名为login_page
    re_path(r'^index/$', views.index,name='index_page'), # 路径index/的别名为index_page
]

在views.py中

python 复制代码
from django.shortcuts import render 
from django.shortcuts import reverse # 用于反向解析
from django.shortcuts import redirect #用于重定向页面
from django.shortcuts import HttpResponse

def login(request):
    if request.method == 'GET':
        # 当为get请求时,返回login.html页面,页面中的{% url 'login_page' %}会被反向解析成路径:/login/
        return render(request, 'login.html')
	
    # 当为post请求时,可以从request.POST中取出请求体的数据
    name = request.POST.get('name')
    pwd = request.POST.get('pwd')
    if name == 'egon' and pwd == '123':
        url = reverse('index_page')  # reverse会将别名'index_page'反向解析成路径:/index/       
        return redirect(url) # 重定向到/index/
    else:
        return HttpResponse('用户名或密码错误')


def index(request):
    return render(request, 'index.html')

login.html

python 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<!--强调:login_page必须加引号-->
<form action="{% url 'login_page' %}" method="post">
    {% csrf_token %} <!--强调:必须加上这一行,后续我们会详细介绍-->
    <p>用户名:<input type="text" name="name"></p>
    <p>密码:<input type="password" name="pwd"></p>
    <p><input type="submit" value="提交"></p>

</form>
</body>
</html>

index.html

python 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h3>我是index页面...</h3>
</body>
</html>

测试

python 复制代码
python manage.py runserver 8001  
# 在浏览器输入:http://127.0.0.1:8001/login/ 会看到登录页面,输入正确的用户名密码会跳转到index.html
# 当我们修改路由表中匹配路径的正则表达式时,程序其余部分均无需修改

总结:

python 复制代码
在views.py中,反向解析的使用:
	url = reverse('index_page')
在模版login.html文件中,反向解析的使用
	{% url 'login_page' %}

无名分组反向解析

python 复制代码
url(r'^index/(\d+)/',views.index,name='xxx')

#后端反向解析
print(reverse('xxx',args=(111,)))   #index/111/

#前端反向解析
<a href='{% url 'xxx' 222 %}'>ppp</a>
相关推荐
点云SLAM9 分钟前
PyTorch 中contiguous函数使用详解和代码演示
人工智能·pytorch·python·3d深度学习·contiguous函数·张量内存布局优化·张量操作
尘浮72822 分钟前
60天python训练计划----day45
开发语言·python
哆啦A梦的口袋呀33 分钟前
基于Python学习《Head First设计模式》第六章 命令模式
python·学习·设计模式
努力搬砖的咸鱼35 分钟前
从零开始搭建 Pytest 测试框架(Python 3.8 + PyCharm 版)
python·pycharm·pytest
Calvex38 分钟前
PyCharm集成Conda环境
python·pycharm·conda
一千柯橘1 小时前
python 项目搭建(类比 node 来学习)
python
洗澡水加冰1 小时前
n8n搭建多阶段交互式工作流
后端·llm
陈随易1 小时前
Univer v0.8.0 发布,开源免费版 Google Sheets
前端·后端·程序员
sduwcgg1 小时前
python的numpy的MKL加速
开发语言·python·numpy
大模型真好玩1 小时前
可视化神器WandB,大模型训练的必备工具!
人工智能·python·mcp