django 之 路由系统
模式:url -----> 函数
静态路由:
指的是写死的url,对应的某个视图函数的操作!要想看到相对应的模版,还需要手动在浏览器的地址栏中敲,前提是你知道这个url,否则就呵呵了!
基础中写的全是静态路由: /login/ -> def login
动态路由:
利用正则去匹配,同时兼顾seo权重的问题(爬虫爬取规则)
- seo权重:是搜素引擎匹配的规则
- 注意点:get传参虽然可以实现功能,但是传值的参数会经常变动,同时这种方式的权重太低,并且安全性不高,数据在地址栏上直接就能显示!
get传参标志---> ? 为避免这种问题,尽量少用。
- URL 实质还是正则表达式,网页地址栏敲地址,实质上还是在与正则做匹配!
避免get传值:
1. 正则匹配urls页面,此时视图函数就需要再写一个形参,用于接收这个固定url后的值。
- 按位(顺序)传参
/add-user/(\w+)/ -> def add_user(request,a1) --- a1会接收(\w+)匹配传递的值 /add-user/(\w+)/(\w+)/ -> def add_user(request,a1,a2) --a1 是接收第一个,a2是接收第二个 - 此处一定要注意:匹配给视图函数传值;函数在接收的时候,是严格按照顺序接收的!
- 指定传参,按照名称传递(不再按照顺序)
/add-user/(?P<a1>\w+)/ -> def add_user(request,a1) /add-user/(?P<a1>\w+)/(?P<a2>\w+)/ -> def add_user(request,a1,a2)
注意:
在路由系统中:按顺序传参和指定名称传参不能混用,要不然视图函数无法完成匹配接收。就是万能的(*args,**kwargs)也无法相对应接收!所以书写的时候一定要统一用法。顺序传参由:args接收;按照指定名称传参由kwargs接收!
PS:
终止符$:
- 如果页面没有终止符,那么网址之后就可以任意的写urls或是多个urls拼接在一起,这样也可以访问页面。
但是我们不希望是有这种情况发生,毕竟不同的urls对应着不同的页面,所以urls之后写上终止符,只有写上固定的URL才能访问,其他的都不行。
^edit$
伪静态:
- 在urls之后加上.html,伪装成固定的静态网站(特点:速度快!)权重最高!
url(r'^edit/(\w+).html$', views.edit),
2. 路由分发:(应用于多个app开发)
- 首先明确一点:多个app代表多个不同的业务。
- 用于解决多部门间协同开发同一框架上不同的业务功能模块的方法。
这种机制是让每个业务线操作写路由关系urls的时候互不干预,避免同时操作一个文件导致url重复的问题!
- 路由分发配置:
1、app文件中复制一份urls.py文件,py文件中用于书写当前app的对应关系
2、在项目主目录下mysite的urls.py文件中导入include
from django.conf.urls import include 配置: url(r'^app文件名/', include('app文件名.urls')), #注意:全是字符串格式 示例: urls.py url(r'^app01/', include('app01.urls')), app01.urls.py url(r'^index.html$', views.index),
执行原理:
把路由匹配分成了两级,先在项目中的urls.py中匹配路由,路由urls指向对应的app文件,然后会在去app文件下的urls.py匹配相对应的url。
3、默认路由:(常用于访问出错,或是路由不匹配的情况下返回的固定信息)
- 所有路由都没有匹配成功,再执行的路由关系,返回固定的提示或是固定的某个页面
示例: from app01 import views from django.shortcuts import HttpResponse def default(request): return HttpResponse('哥们,走错了。。') url(r'^',default ),#返回固定的提示! views.py def index(request): return render(request,"index.html") url(r'^', views.index), #返回默认页面
4、命名:用于根据名字反向生成url
(最大特点:可以通过名字反向生成url,用以应对 书写或是存储 复杂或是长的 路径)
- 给urls.py文件中的对应关系,命名 name = "xxx" /add-user/(\d+)/ -> def add_user(request,a1) name=n1
根据名称可以反向生成URL
1. 在Python代码中 :通过request 和参数反生成url
from django.urls import reverse def add_user(request,a1) v = reverse('n1', args=xxx, #对应顺序传参 kwargs={'a1':1111} #对应按位传参 #为url传值,生成新的url,想获取什么url就获取什么url 两种方式二选一 ) print(v) return render(request,"index.html") 浏览器地址栏:127.0.0.1:8000/index/123 后台拿到的v: index/1111
2. 在模版页面中,也可以根据名称反生成url(视图函数中不用传值,也不用返回值)
- 没有参数的情况: 视图函数中: def login(request) return reder(request,"login.html") 模版文件中: url(r'^login/', views.login,name='m1') {% url "m1" %} - 有参数,传值: 视图函数中: def login(request,a1(*args)) return reder(request,"login.html") 模版文件中: url(r'^login/', views.login,name='m1') {% url "m1" 值 %} #按照顺序传值 单个值 {% url "m1" 值1 值2 %} #按照顺序传值 多值 #写值的时候,一定要注意空格!
5、URL 路由分发中 关于 namespace
我们在写路由分发的时候都是用include("app名字.urls") 实现。我们查看include源码发现,这个方法最后 return [],appname,namespace,[]第一个列表代表所有的url地址,
namespace 和url中的name一样指定这个include,所以,当我们做路由分发的时候,可以指定namespace的值也可以不写,传入的值可以是个列表,也可以是个字符串类型的文件地址(本质是获取这个文件内的url列表)。
我们知道,可以通过name反解出详细的url地址,那如果有namespace怎么办?起始Django内部给了我们解决办法:reverse("namespace:name"),反解的时候将namespace与name通过冒号拼接;如果是有多层的include,及多个namespace(可以不写),
当我们进行反解url的时候,就需要从最外层的namespace通过冒号(:),一直拼接到name,如下:reverse("namespace1:namespace2:..:name")。
namespace 作用是url间的分割,name命名的隔离。其最主要的一点是:在反向生成url的时候,避免name相同的情况下出现混淆;支持嵌套,只要是namespace不同即可。
url(r'^app01/', include([ url(r'^login/', include([ url(r'^log/', views.login, name='login'), ],namespace='n2')), url(r'^logout/', views.logout, name='logout'), url(r'^test/', views.test), ], namespace='n1')), url(r'^app02/', include([ url(r'^login/', include([ url(r'^log/', views.login, name='login'), ],namespace='n2')), url(r'^logout/', views.logout, name='logout'), url(r'^test/', views.test), ], namespace='n2')) ] from django.urls import reverse def test(request): # 反向生成login和logout的url print(reverse('n1:n2:login')) print(reverse('n1:logout')) return HttpResponse('...')