Django框架之路由层
2、路由层
urls.py文件就是路由层,与视图层有一一对应关系的
1、路由匹配
路由匹配是按照正则匹配,url方法中第一个参数是正则表达式,一旦匹配到内容就会立刻执行对应的视图函数
urlpatterns = [ url(r'^admin/', admin.site.urls), # 首页匹配 url(r'^$', views.home), # ^ 是以什么开头,$ 是以什么结尾 url(r'^test/', views.test), # 不加 / Django会自动加上,会发送两次请求第一次重定向到加/的请求url上,可以在配置文件中修改此配置 # APPEND_SLASH = True/False url(r'^test_add', views.test_add) ]
2、无名分组
分组:就是给一段正则表达式加括号
无名分组:在路由匹配的时候给某段正则表达式加括号,匹配的时候会将括号内的正则表达式匹配到的内容当做位置参数传递给对应的视图函数
# 无名分组 url(r'^test/([0-9]{4})/',views.test) # 视图函数,需要用一个位置参数接收url正则内无名分组的内容 def test(request,args): return HttpResponse('test')
3、有名分组
有名分组:给一段正则表达式加括号,括号内用 ?P<名字> 作为分组的名字,把括号里面的内容当做关键字参数传递给视图函数
# 有名分组 url(r'^test_add/(?P<name>[0-9]{4})', views.test_add), # 视图函数,需要接收一个关键字参数与url传递的关键字参数一样 def test_add(request, name): return HttpResponse('test_add')
无名分组和有名分组不能混合使用,但是同一种命名方式可以使用多个
url(r'^test/([0-9]{2})/(\d+)/',views.test), url(r'^test/(?P<name>\d+)/(?P<year>[0-9]{3})/',views.test),
4、反向解析
通过一些方法,能够得到一个结果,该结果可以访问到对应的url,当项目中后端和前端很多地方都要使用url路径中的参数,而为了调转url不会影响后端views和前端的代码,给这个url起一个别名,相当于动态绑定就是反向解析
1、普通反向解析
1、先在路由与视图函数对应关系中起一个名字,name
url(r'^test/', views.test, name = 'add')
2、后端解析,先导入模块reverse,再调用该模块
from django.shortcuts import render,HttpResponse,redirect,reverse reverse('add') # 拿到url绑定name='add'的url地址
3、前端解析
{% url 'add' %} # 拿到url绑定name='add'的url地址
2、无名分组反向解析
1、路由层,给无名分组的 url 起别名,name
url(r'^testadd/(\d+)/',views.testadd,name='add')
2、后端解析,需要指定位置参数数字,与url分组中输入的数字位数相同即可,这个数字一般是数据的主键
reverse('add',args=(12,)) # args中是元组,数字位数要与url中分组输入的相同
3、前端解析,需要属于一个数字与url中输入的数字位数相同,这个数字一般是数据的主键
{% url 'add' 11 %} # 数字要与url中输入的数字位数相同
3、有名分组反向解析
1、路由层,给有名分组的 url 起别名,name
url(r'^test/[0-9]{2}/', views.test, name='test_id')
2、后端解析,需要一个关键字参数接收分组中与url中分组输入的数字位数相同的数,这个数字一般是数据的主键
reverse('add', kwargs={'test_id':11}) reverse('add', args=(11,)) # 可以使用位置参数接收,推荐使用
3、前端解析,需要指定一个关键字参数来接收数据位数相同的数,这个数字一般是数据的主键
{% url 'add' test_id=11 %} {% url 'add' 11 %} # 可以使用无名分组反向解析的方法,推荐使用
5、路由分发
当Django项目比较庞大时,路由与视图函数对应关系太多,总路由代码会很冗长,不好维护,Django支持每一个app都可以有自己的urls.py ,并且总路由不要做路由与视图函数的对应关系了只做分发任务的操作
根据请求不同,识别是哪个app,然后自动将下发到对应的app下的urls.py文件中再做与视图函数对应关系,每个app不仅可以有自己的urls.py 还可以有static文件夹,templates文件夹,便于分小组开发
1、总路由,需要分发模块 include()
注意:在路由分发时,应用名后不能加$
from django.conf.urls import url,include # 路由分发 注意事项应用名后面千万不能加$ # from app01 import urls as app01_urls # from app02 import urls as app02_urls # url(r'^app01/',include(app01_urls)), # url(r'^app02/',include(app02_urls)) # 简写, 使用这种 url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls'))
2、子路由,在子路由中urls中写与视图函数对应关系
from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^index/',views.index) ]
3、名称空间
当我们的项目有多个app时,并且每个app下都针对匹配的路径起了别名,当别名相同时,那么在反向解析时就会出现覆盖,解决这个问题就是避免起名重复,或者使用Django的名称空间
1、在总路由分发时,指定名称空间, namespace
url(r'^app01/',include('app01.urls',namespace='app01')) url(r'^app02/',include('app02.urls',namespace='app02'))
2、后端解析
reverse('app01:index') reverse('app02:index')
3、前端解析
{% url 'app01:index' %} {% url 'app02:index' %}
一般我们起别名时加上应用名作为前缀就不会出现此问题了
url(r'^index/',views.index,name='app01_index') url(r'^index/',views.index,name='app02_index')
4、虚拟环境
我们想针对不同的项目,只安装项目所需要的功能模块,项目不用的不安装,来避免加载资源的耗时,就创建一个虚拟环境
创建虚拟环境就类似于装一个纯净的python解释器,所有每创建一个虚拟环境,就相当于重新下载一个python解释器,不推荐使用太多,会占硬盘内存
5、Django版本区别
1.x版本路由层用的是url,第一个参数使用的正则表达式
2.x版本路由层用的是path,不支持使用正则表达式,但是2.x和3.x版本提供了re_path等价于1.x版本中的url功能
虽然path不支持正则表达式但是提供了五种默认的转换器
str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式 int,匹配正整数,包含0。 slug,匹配字母、数字以及横杠、下划线组成的字符串。 uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。 path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
除了默认的五种表达式还支持自定义的转换器
class MonthConverter: regex='\d{2}' # 属性名必须为regex def to_python(self, value): return int(value) def to_url(self, value): return value # 匹配的regex是两个数字,返回的结果也必须是两个数字
6、伪静态
伪静态:url以.html结尾给人的感觉像是文件中的,写死的,内容不会轻易的改变,其实本质就是将路由层的第一个参数名换成了以.html 结尾
伪静态作用:为了提高你的网站的搜索引擎的力度,提供网站的SEO查询效率