Django基础(三)

django请求生命周期流程图

路由层

1.路由匹配

2.无名有名分组

3.反向解析

4.名称空间

5.路由分发

django请求声明周期流程图

客户端先基于HTTP协议将请求数据通过web服务网关接口的时候,被wsgiref模块解析并封装发给django后端,进入后端之后先经过类似于保安的中间件,然后再到达路由层(urls.py)寻找对应关系,接下来就会去视图层(views.py)找到与路由层对应的关系,如果需要使用到模板层就通过模板语法进入到模板层(templates.py),找到需要的数据再返回视图层;如果需要使用到模型层,就通过orm操作进入到模型层(models.py),操作完之后再将获得的数据返回到视图层,然后再经过视图层、路由层、中间层又到达wsgiref,然后将需要数据打包发送到前端页面

路由层之路由匹配

路由匹配的特点,只要匹配上了就会立刻结束执行对应的视图函数,并且url方法的第一个参数其实是一个正则表达式,只要正则表达式能够从用户输入的后缀中匹配到内容就算匹配上了!
eg:
    正则是test   内容是test  那么可以匹配出test文本
    正则是test   内容是testadd  那么还可以匹配出test文本
    都算匹配上了
    
演变过程
	正则是test/内容是test 那么首次无法匹配
 # django二次追加斜杠机制
	首次匹配不上,那么django还会让浏览器默认加斜杆再次发送请求
  第一次:  test     报301错
  第二次:	test/    会自动在后面加上斜杆
    
  # 斜杆机制可以取消,但是不推荐
	APPEND_SLASH = False
    
 正则是test/ 内容是abcdefgtest/ 也可以匹配出文本test/
  	可以在正则的最前面加上上箭头来限制
  	'''解决路由前面可以随意乱写的问题'''
    
  正则是^test/ 内容是test/abc/edf/acd/ 也可以匹配出文本test/
  	可以在正则的最后面加上$来限制
    '''解决路由后面可以随意乱写的问题'''
    
# 由于第一个参数是正则,所以当项目特别大,对应关系特别多的时候要格外注意是否会出现路由顶替的现象
小扩展:
	1.可以定制一个主页面,用户不携带后缀可以直接访问(掌握)
    url(r'^$',views.home)
    
    2.可以定义一个尾页,用户输入一个没有对应关系的直接返回(了解)
    url(r'.*',views.error)

无名有名分组

url(r'^test/([0-9]{4})/$',views.test)   		# 0-9之间随便取四个数字都可以访问
路由匹配成功之后就会调用视图函数默认请款下会自动给视图函数船体一个request位置参数
test(request)
如果路由匹配中使用括号对正则表达式进行了分组,那么在调用视图函数的时候会将括号内匹配到的内容当做位置参数传递给视图函数
test(request,括号内正则表达式匹配到的内容)
这种特性django称之为'无名分组'

url(r'^testadd/(?P<user_id>[0-9]{4})$', views.testadd)
给括号内的正则表达式起别名之后 匹配成功则会讲括号内匹配到的内容按照关键字参数传递给视图函数
testadd(request,user_id=括号内正则表达式匹配到的内容)
上述特性django称之为'有名分组'

# 两者是否可以混合使用
  url(r'^test/(\d+)/(?P<user_id>[0-9]{4})/$', views.testadd)  # 不可以
  无名有名分组不能混合使用!!! 单个可以重复使用
  url(r'^test/(\d+)/(\d+)/$', views.testadd)   # 可以
  url(r'^test/(?P<a>\d+)/(?P<b>\d+)',views.testadd)  # 可以

反向解析

"""
a标签的href可以写网址的全称 也可以写后缀
	href='https://www.baidu.com'
	href='/login/'  # 自动补全当前服务的ip和port
		href='127.0.0.1:8000/login/'
"""
1.页面上有很多a标签链接了其他路由
2.路由匹配表达式出现了变化 html页面上的地址全部失效

# 反向解析
通过反向解析可以获取到一个结果,该结果可以访问到一个路由

步骤1:给对应关系起别名
url(r'^func666/',views.func,name='view')
步骤2:使用反向解析获取结果
# 前端:{% url 'func_view' %}  # func666/   结果可以访问路由
# 后端:from django.shortcuts import reverse
		reverse('func_view')	# func666/	结果可以访问路由
    
# 无名分组反向解析
步骤1:给对应关系起别名
url(r'^func666/(\d+)/',views.func,name='func_view')
步骤2:使用反向解析获取结果(因为无法明确括号内正则表达式的内容,需要人为指定)
# 前端:{% url 'func_view' 123 %}		# func666/123/
# 后端:from django.shortcuts import reverse
	   reverse('func_view',args=(666,)) 	# func666/666/

    
# 有名分组反向解析
步骤1:给对应关系起别名
url(r'^func666/(?P<id>\d+)/',views.func,name='func_view')
步骤2:
# 前端:{% url 'func_view' 123 %}		# func666/123/
  	    {% url 'func_view' id=123 %}	# func666/123/
# 后端:from django.shortcuts import reverse
		reverse('func_view',args=(666,))	# func666/666/
    	reverse('func_view',kwargs={'id':1})	# func666/1/

# 无名有名反向解析中的手动传值,这个值在实际工作中可以是数据的主键值、页面的页码、区域的编号等

路由分发

如果一个django项目特别庞大,里面有很多应用,每个应用下有很多对应关系,那么django自带的路由层里面的代码就会非常非常的多,我们可以根据应用的不同拆分到不同的应用中来优化

django支持每个应用都可以有自己独立的路由层、模块层、静态文件、视图层(默认)、模型层(默认)

上述特性能够让django在分组开发上更加的方便、快捷,所有人都可以在应用中开发完整的项目功能,最后汇总到一个空的django项目中,然后通过路由分发整合所有人的应用

1.创建多个应用 并去配置文件中注册
	INSTALLED_APPS = [
    'app01',
    'app02'
]
 
2.在多个应用中编写相同的路由
  urlpatterns = [
    url(r'^index/',views.index111)
]
	urlpatterns = [
    url(r'^index/',views.index)
]
    
3.路由分发
	总路由
  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))
  """总路由只负责分发 不负责视图函数对应"""
  上述代码还可以简写
  from django.conf.urls import url, include
  url(r'^app01/',include('app01.urls')),
  url(r'^app02/',include('app02.urls'))

名称空间

1.不同的应用使用了相同的别名 那么反向解析是否自动识别
	index_view				app01/index/
  index_view				app02/index/
2.验证发现默认情况下是不会自动识别应用前缀的 如何解决反向解析问题
	方式1:名称空间
    	总路由添加名称空间
    url(r'^app01/',include('app01.urls',namespace='app01')),
    url(r'^app02/',include('app02.urls',namespace='app02'))
    	应用反向解析自动提示
      	reverse('app01:index_view')
        reverse('app02:index_view')
        {% url 'app01:index_view' %}
        {% url 'app02:index_view' %}
  方式2:只需要确保反向解析的别名在整个项目中不重复即可!!!
    	可以在别名的前面加上应用名的前缀
      	url(r'^index/',views.index,name='app01_index_view')
        url(r'^index/',views.index,name='app02_index_view')
"""
名称空间其实是可有可无的知识 但是在实际工作中还是有不少程序员喜欢使用
"""