【2022-09-01】Django框架(三)

Django框架(三)

Django请求生命周期流程图

扩展知识点

缓存数据库
		浏览器向后端发送请求,在经过 Django 中间件之后,会先从缓存数据库寻找数据,如果没有则向后端数据库要数据。后端返回数据结果的同时在缓存数据库保存一份,类似于 DNS 的解析过程
    
  		作用:提高效率和响应时间
Nginx简介

    Nginx (engine x) 是一款轻量级的 Web 服务器 、反向代理服务器及电子邮件(IMAP/POP3)代理服务器。Nginx 是开源的轻量级 Web 服务器、反向代理服务器,以及负载均衡器和 HTTP 缓存器。其特点是高并发,高性能和低内存。
    
    1、采用epoll模型,事件驱动,支持高并发连接:能够支撑5万并发连接,实际生产环境中可以支撑2~4万并发连接数。主要是Nginx使用了最新的epoll(Linux2.6内核)和kqueue(freeBSD)网路I/O模型,而Apache使用的是传统的Select模型,其比较稳定的Prefork模式为多进程模式,需要经常派生子进程,所以比Nginx更消耗CPU等服务器资源。
    2、内存消耗少:Nginx+PHP(FastCGI)服务器,在3万并发连接下,开启10个Nginx进程消耗150MB内存,开启的64个PHP-CGI进程消耗1280内存,加上系统自身消耗的内存,总共消耗不到2GB的内存。如果服务器的内存比较小,完全可以只开启25个PHP-CGI进程,这样PHP-CGI消耗的总内存数才500MB。
    3、成本低廉:购买F5BIG-IP、NetScaler等硬件负载均衡交换机,需要十多万到几十万人民币,而Nginx为开源软件,采用的是2-clause BSD-like协议,可以免费试用,并且可用于商业用途。BSD开源协议是一个给使用者很大自由的协议,协议指出可以自由使用、修改源代码、也可以将修改后的代码作为开源或专用软件再发布。
    4、配置文件非常简单:网络和程序一样通俗易懂,即使,非专用系统管理员也能看懂。
    5、支持Rewrite重写:能够根据域名、URL的不同,将http请求分到不同的后端服务器群组。
    6、内置的健康检查功能:如果NginxProxy后端的某台Web服务器宕机了,不会影响前端的访问。
    7、节省带宽:支持GZIP压缩,可以添加浏览器本地缓存的Header头。
    8、稳定性高:用于反向代理,宕机的概率微乎其微,内置健康检,Nginx 代理的后端的某台服务器宕机了,会自动不访问该机器
    9、支持热部署:Nginx支持热部署,它的自动特别容易,并且,几乎可以7天*24小时不间断的运行,即使,运行数个月也不需要重新启动,还能够在不间断服务的情况下,对软件版本进行升级。
Nginx正向代理和反向代理
    	正向代理:请求经过代理服务器从局域网发出,然后到达互联网上的服务器。
    	特点:服务端并不知道真正的客户端是谁。
    	反向代理:请求从互联网发出,先进入代理服务器,再转发给局域网内的服务器。
    	特点:客户端并不知道真正的服务端是谁。
    	区别:正向代理的对象是客户端。反向代理的对象是服务端。

简单说一下从用户发送请求到用户获得响应结果的大致流程

浏览器发送http请求先到nginx,nginx接收到浏览器发送过来的http请求并进行解析,分析url,如果是静态文件请求就直接返回nginx配置的静态文件目录,直接返回用户请求的静态文件。
如果不是静态文件的请求而是一个动态请求,那么nginx就将请求转发给uwsgi,uwsgi接收到请求之后并进行解析处理,处理成wsgi可以接收的格式,并发给wsgi,wsgi根据请求调用相应的API,也就是我们用框架(django,flask)写的接口,调用完之后把处理的返回值再交给wsgi,wsgi将返回值进行打包,打包成uwsgi能接收的格式,uwsgi接收wsgi发送的请求,并转发给nginx,nginx最终将返回值返回给浏览器。

路由层之路由匹配

  • 路由匹配的特点是 只要匹配上了就会立刻结束执行对应的视图函数,并且url方法的第一个参数其实是一个正则表达式
path('网址后缀',函数名)
	一旦网址后缀匹配上了就会自动执行后面的函数 
  	并结束整个路由的匹配
 
1.路由结尾的斜杠
	默认情况下不写斜杠 django会做二次处理 
    	第一次匹配不上 会让浏览器加斜杠再次请求
 	django配置文件中可以指定是否自动添加斜杠
    	APPEND_SLASH = False
        
2.path转换器
	当网址后缀不固定的时候 可以使用转换器来匹配
    	'int': IntConverter(),
        'path': PathConverter(),
        'slug': SlugConverter(),
        'str': StringConverter(),
        'uuid': UUIDConverter(),
   path('func/<int:year>/<str:info>/', views.func)	
   转换器匹配到的内容会当做视图函数的关键字参数传入
   转换器有几个叫什么名字 那么视图函数的形参必须对应
  	def func(request,year,info):
  		pass
    
3.re_path正则匹配
	re_path(正则表达式,函数名)
    一旦网址后缀的正则能够匹配到内容就会自动执行后面的函数 
    并结束整个路由的匹配
  	re_path('^test/$', views.test)
 	当网址后缀不固定的时候 可以使用转换器来匹配
    
4.正则匹配之无名分组
	re_path('^test/(\d+)/', views.test)
   正则表达式匹配到的内容会当做视图函数的位置参数传递给视图函数

5.正则匹配之有名分组
   re_path('^test/(?P<year>\d+)/(?P<others>.*?)/', views.test)
   正则表达式匹配到的内容会当做视图函数的关键字参数传递给视图函数

6.django版本区别
	在django1.11中 只支持正则匹配 并且方法是 url()
 	django2,3,4中  path()  re_path() 等价于 url()

无名有名分组

	url(r'^test/([0-9]{4})/$', views.test)
	"""
	路由匹配成功之后就会调用视图函数默认情况下会自动给视图函数传递一个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='func_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:名称空间
	    	总路由添加名称空间
            path('app01/', include(('app01.urls', 'app01'), namespace='app01'))
            path('app01/', include(('app01.urls', 'app02'), 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')
	"""
	名称空间其实是可有可无的知识 但是在实际工作中还是有不少程序员喜欢使用
	"""

posted @ 2022-09-01 21:58  dy12138  阅读(117)  评论(0)    收藏  举报