首页 > 其他分享 >django之路由层

django之路由层

时间:2023-06-26 15:22:32浏览次数:27  
标签:匹配 views django path login 解析 路由

目录

django之路由层

路由层,主要是路由地址与视图函数的映射关系,如果将网站比作一本书,那么路由就相当于这本书的目录。

路由匹配

在目前的主流版本2.x及以上版本中,我们默认采取path函数记录映射关系,

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.home_page),
    path('article/<str:info>/', views.article_page),
    path('register/', views.register_page),
    path('login/', views.login_page),
]

path函数的第一个参数就是预设的各种路由,当我们在网页中输入网址,我们浏览器会将网址中路由解析出来依次与我们预设的路由比对,如果比对成功会去path()的第二个参数所对应的视图函数中(自动传入request对象作为第一个实参)执行并返回一个界面。

如果没有这么一个界面,那么django也提供了默认返回的界面如下:

img

这个网页会提示我们没有找到对应的网页,并且提示我们为什么找不到。

如这里就是没有提前配置我们胡乱输入的路由asef

django1.x版本默认使用的配置对应函数的方式是url("", views.func),其第一个参数是以正则表达式的方式匹配我们的路由的。

路由匹配小优化

在django的任何版本中,如果我们在输入路由时没有在后面跟/,那么在匹配不到路由时,会加上斜杠再请求匹配一遍。

验证:我们预设的路由中有'admin/',那么我们只输入路由中只输入admin,观察其网络请求的情况:

img

这个路由匹配优化可以在配置文件中设置取消APPEND_SLASH = False,不过一般不会这样折磨用户。

转换器

正常情况下很多网站都会有很多相似的网址,如果我们每一个都单独开设路由不合理。

django2.X版本及以上提供了动态匹配转换器:path('article/<str:info>/', views.article_page)

其中用小尖括号括起来的<str:info>就可以捕捉路由中这个位置的所有字符串,并以关键字参数的形式传送到对应的功能函数中,这种将一类路由都分组到一个路由配置的方式又称作有名分组

img

我们定义以下视图函数来测试一下参数效果:

def article_page(request, info):
    print(info)
    return HttpResponse(f'article_{info}展示')

img

注意以下易错点

转换器所捕捉的路由会作为关键字参数传入功能函数,于是:

  • 视图函数需要提前定义对应数量的形参
  • 视图函数所定义参数的形参名必须与传入的关键字实参对应

转换器种类

  • str:匹配除路径分隔符外的任何非空字符串。
  • int:匹配0或者任意正整数。
  • slug:匹配任意一个由字母或数字组成的字符串。
  • uuid:匹配格式化后的UUID。
  • path:能够匹配完整的URL路径

转换器不仅可以捕捉匹配的内容,还会将其转换成对应的数据格式,而我们常用的就是str转换器。

正则匹配

在1.X中为默认而在2.X及以上版本也依然可以使用的匹配方式,第一个参数为正则。

这种匹配方式很灵活,但是对于路由匹配而言,并不是匹配到越多的路由就越好,因为也并不一定有对应的界面可以返回给用户。

在2.X版本中,正则匹配关键字为re_path(),1.X版本则为url()

无名分组与有名分组

  • re_path('^test/\d{4}/', views.test)
    如果匹配到test路由后跟四个数字的路由,就转去test函数
  • re_path('^test/(\d{4})/', views.test)
    匹配到后,会将括号中匹配的内容作为位置参数传入test
  • re_path('^test/(?P<year>\d{4})/', views.test)
    匹配到后,会将括号中匹配的内容作为关键字参数传入test

注意:可以分多组进行传参,但是不能混用无名分组和有名分组。

反向解析

静态路由的反向解析

path('login_page/', views.login) 
↓↓↓↓↓↓ 
path('login/', views.login)  # 改变了预设路由

在路由配置完成后,可能存在需要改路由名的情况,但是一旦改动,原本引用这处路由的网址都会失效:

  • templates模板中的html文件的a标签
  • 视图函数的重定向所引用的网址

django考虑这点,提供了反向解析的方法:

通过一个名字可以反向解析出一个结果,通过这个结果可以访问到某个路由。

我们只需要在path函数再添加一个关键字参数name,就相当于给路由起了个别名。

path('login_page/', views.login, name='login_view') 
↓↓↓↓↓↓ 
path('login/', views.login, name='login_view')  # 改变了预设路由

这样我们在可能会失效的链接处都采取反向解析语法,就可以通过login_view解析出路由,用户在去访问链接能对应上了。

反向解析语法

  • urls文件:path('别名', 视图函数, name='别名')
  • html页面:{% url '别名' %}
  • 后端语法:reverse('别名')

这两句语法都会返回一个完整的网址(即域名+路由)的形式。

{% url 'login_view' %}  # 网页上的用法
reverse('login_view')  # 后端的用法

动态路由的反向解析

对于静态路由,我们可以通过一个别名来对应这个路由,而面对可以匹配很多路由的动态路由,通过一个别名来对应显然是不合适的。

动态反向解析语法

  • 路由文件:path('路由/转换器/', 视图函数, name="别名")
  • html页面:{% url '别名' 匹配项 %}
  • 后端语法:reverse('别名', args=(匹配项1,))

例子:

# urls.py
path('modify/<str:modify_id>/', table_crud_views.modify_func, name='modify_func'),

# html页面
<a class="btn btn-info btn-sm" href={% url "modify_func" user_dict.id %}>修改</a>
# 如果这里的id值从字典里取出来是1,则得到 顶级域名/modify/1/

# 后端重定向
def func(request):
    match1 = '一个匹配项'
    return redirect(reverse("modify_func", args=(match1,)))  
# reverse得到的 顶级域名/modify/一个匹配项/

路由分发

django支持每个应用可以有独立拥有路由层。而这样就方便我们每个开发项目的开发完全解耦合,而每个应用独立的路由文件又可以通过路由分发整合到一起。

如我们在app01的文件夹中新建一个urls.py

from django.urls import path  # 需要导入path函数
from app01 import views  # 这个软件的视图导入

urlpatterns = [
    path("login/", views.login)  
]  # 在每个app中路由编写还是一样的

也可以相似的在app02中,也新建一个urls.py编写它的路由:path("login/", views.login)

两个软件的路由可能会冲突,但是用了路由分发就不会避免路由的冲突,视图函数的命名也不必特地避免重复了。

我们在django项目的同名文件夹下的总路由编写:

# django_project/urls.py中
from django.urls import path,include  # 导入path和include方法

urlpatterns = [
    path('app01/', include("app01.urls")),
    path('app02/', include("app02.urls")), 
]  # include函数帮我们将urls文件中的路由全部拼起来了 

img

路由分发后的反向解析

路由分发之后,针对相同的别名能否自动反向解析出不同的应用前缀?

答案是:默认情况下是无法直接识别应用前缀的

解决方案有两种:

  1. 别名定个规范:每个app的路由别名都加app前缀

    # app自己的路由中
    path('index/', views.index, name='app01_index_view')  # app01中
    path('index/', views.index, name='app02_index_view')  # app02中
    
  2. 名称空间:官方提供的方法,能帮我们识别前缀

    # 总路由中
    path('app01/', include(('app01.urls', 'app01'), namespace='app01')),
    path('app02/', include(('app02.urls', 'app02'), namespace='app02')),
    

无论是哪种方法,在反向解析时,其别名的引用都发生了更改,如:

方法1reverse('app01_index_view')和方法2reverse("app01:index_view")

所以这必须是在立项前就要确认好的细节,或者干脆就不要起别名,把路由给定死。

标签:匹配,views,django,path,login,解析,路由
From: https://www.cnblogs.com/wxlxl/p/17505719.html

相关文章

  • 前端实现权限控制 - 三种方法 - 不同的角色有不同的路由映射
     有代码:https://gitee.com/zhu-longxu/zhulx-rbacps:注意本地路由router有哪些规则?服务器返回的数据格式? 方法一:本地路由router包含静态路由规则;虽然动态路由规则定义了但是没有注入;动态路由规则在登录判断的时候选择性是否注入;服务器返回数据格式 [ "news", "cat......
  • 双网卡上网指定route路由DNS
    双网卡指定上网出口route路由DNS方法如下:route-padd10.130.0.0mask255.255.0.010.130.2.254routedelete0.0.0.0route-padd0.0.0.0mask0.0.0.0192.168.4.1第一条命令route-padd10.130.0.0mask255.255.0.010.130.2.254效果:NetworkAddressNetmask......
  • vue的路由(更新中)
    路由含义及原理路由(router)就是对应关系。地址与页面上组件的对应关系。Hash地址与组件之间的对应关系!锚链接锚链接不会使页面刷新,但有浏览历史。(AnchorLink)是指在网页中通过链接跳转到同一页面的不同位置的技术。它可以让用户通过点击链接或者页面内部的锚点,直接跳转到页面......
  • django 环境和安装 + job - 蓝v - django.core.exceptions.ImproperlyConfigured: SQL
    1.部署蓝鲸2.安装djangomkdir~/.virtualenvspython3-mvenv~/.virtualenvs/djangodevpython-mvenv~/.virtualenvs/djangodevsource~/.virtualenvs/djangodev/bin/activatedeactivatesource~/.virtualenvs/djangodev/bin/activatepipinstallDjangopython-c&quo......
  • flask中添加路由的方式
    在Flask中,添加路由有两种方式:(一般情况下都是用第一种方式)方式一:常见的装饰器模式@app.route("/")defindex():return"HelloWorld"方式二:通过阅读装饰器模式添加路由的源码发现 defroute(self,rule,**options):"""Adecoratorthatisusedtoregistera......
  • 11、默认路由(缺省路由)、浮动路由(主备路由)
    静态路由分析可看,管理员配置的路由条目比较多,当网络环境比较大时,路由条目就非常复杂,尤其是部署在企业出口的路由器,不可能明细化配置复杂的静态路由信息,一般在边界路由器配置默认路由,也是静态路由的一种方式。默认路由格式:【H3C】iproute-static0.0.0.00.0.0.0下一跳IP地址......
  • 生产环境访问django后台,提示CSRF验证失败. 请求被中断
    解决方法:登录后复制 settings.py添加这句代码,域名改为你前端ngx的域名CSRF_TRUSTED_ORIGINS=['https://xxxx.demo.com'] ......
  • django 如何在序列化器中抛出错误 并且在视图中捕捉返回给前端
    1.在create()中抛出错误classYourSerializer(serializers.Serializer):defcreate(self,validated_data):#进行数据验证是否满足条件#得到数据过程以省略condition=Falseifnotcondition:#抛出ValidationError异常,......
  • django 上下文管理器 get_context_data 使用
    在Django中,序列化器(serializer)是用于处理数据的序列化和反序列化的类。而get_context_data()方法是用于获取视图上下文数据的方法。默认情况下,序列化器无法直接拿到get_context_data()中的内容。如果你希望将get_context_data()中的内容传递给序列化器进行处理,可以通过以下几种方......
  • vue项目本地启动history路由模式刷新页面404
    背景:之前一直用hash模式,改成history模式后刷新页面404解决:vue.config.js中publicPath:"/"如果是线上服务则还需要后端修改一些配置,见链接点击查看......