django学习第十三天--自定义中间件
jquery操作cookie
- 下载地址
http://plugins.jquery.com/cookie/
- 引入
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.cookie.js"></script>
- cookie操作
设置值:
$.cookie('the_cookie','the_value');
#设置7天有效期
$.cookie('the_cookie','the_value',{expires:7});
读取
$.cookie('the_cookie'); #通过键来取值
删除cookie
$.cookie('the_cookie',null); #通过传递null作为cookie的值即可
中间件
配置文件
项目主目录中的配置文件是django留给开发者使用的用户级别配置文件
实际上django有一个自己的默认全局配置文件
那么他们的关系如下
#django默认配置
from django.conf import global_settings
#用户级别配置
from django_middleware import settinigs
from django.conf import settings #中间人
#比如需要引入配置中的某个配置项settings.APPEND_SLASH,那么这样的引入的查找顺序是这样的,先去用户级别settings.py文件中找这个配置,如果没有找到,那么再去global_settings中去找默认配置
django请求生命周期
中间件用来对请求和响应做一些统一加工和处理的,比如对所有请求中的post请求做一个csrftoken认证,就用到了我们的'django.middleware.csrf.CsrfViewMiddleware',后面视图中能够使用request.session做一个session相关操作,这个request.session的功能就是在这个中间件中加工好的'django.contrib.sessions.middleware.SessionMiddleware'
自定义中间件
- 登录认证、权限认证、频率访问限制、请求数据统计等等...
- 自定义中间的步骤
1.应用文件夹下面创建一个文件夹,名字随便起,比如叫作mymiddleware
2.在mymiddleware文件夹下面创建一个py文件,名称随意,比如叫做middlewares.py
3.在middlewares.py文件中写上如下内容
from django.utils.deprecation import MiddlewareMixin
class LoginAuth(MiddlewareMixin):
def process_request(self,request):
print('xxx')
4.settings.py配置文件中写上如下内容
MIDDLEWARE = [
....
'应用名.中间文件夹.中间文件.类'
'app01.mymiddleware.middlewares.LoginAuth', #配置中间件类,告诉django,我写的这个自定义中间件,你帮我使用上,一般都是放到最后,不然上面几个中间件的相关功能就没办法使用上了。
#如果中间件功能不想用了,就注释掉它就行了。
#以上几步搞定后,所有请求都会触发我们的中间件类中的process_request方法。
]
- 登录认证中间示例
中间件代码如下
#登录认证中间件
class LoginAuth(MiddlewareMixin):
#/login/登录请求,应该正常放行,让他能获得login.html页面
#添加一个白名单,这样首页登录就不需要登录认证
white_list = ['/login/',]
def process_request(self,request):
print('请求来啦!!!')
#获取当前请求路径:request.path /login/
#如果当前请求路径在白名单里面,我们不进行登录认证
if not request.path in self.white_list:
is_login = request.session.get('is_login') #True
if not is_login:
return redirect('/login/')
#视图代码
def login(request):
if request.method == 'GET':
return render(request,'login.html')
else:
#print('xxxxxx')
uname = request.POST.get('username')
if uname == 'root':
request.session['is_login'] = True
return redirect('/home/')#告诉浏览器向/home/发送get请求获取页面
else:
return redirect('/login/')
def home(request):
print('home')
return render(request,'home.html')
def index(request):
print('index')
return render(request,'index.html')
#执行步骤:如判断用户访问home页面,是否已经登录过了
第一次请求的时候,先是走的中间件process_request,login路径,在白名单里面,所以就不会走下面的判断,
实际后面会有个return None,就表示是正常返回,可以省略不用写,然后再去执行视图逻辑,获取到login页面,get请求获取login页面。
第二次填写数据发送post请求,又会走一遍process_request,正常返回后再去执行视图逻辑,后台获取发送来的数据,
设置session,然后重定向到home页面,重定向的时候又会走了一遍process_request,然后中间件会判断这个重定向的路径,最后再执行视图逻辑。
下次想直接访问home页面的时候,先是发送/home/请求,先走中间件process_request,判断当前的路径是不是在白名单里,
显然不在,然后执行下面的逻辑代码,获取到session中的键值对,如获取到了,return None,那么就会执行视图里面的逻辑,就直接执行home函数。
如没有获取到,那么直接在中间件代码里面直接就重定向到login页面。
中间件的五个方法
整个中间件的执行顺序
process_request从上到下,process_response从下到上
- 五个方法:process_request和process_response这个两个是重点
process_request(self,request) #请求
process_view(self,request,view_func,view_args,view_kwargs)#视图
process_template_response(self,request,response)#模板
process_exception(self,request,exception) #错误
process_response(self,request,response) #响应
每个方法的执行流程
- 1.process_request
class Md1(MiddlewareMixin):
def process_request(self,request):
print('MD1--process_request')
#当process_request返回时None,可以默认不写,那么才会继续执行后面的中间件的process_request,如果你是最后一个中间件,并且你返回的是None,那么逻辑会继续执行到我们的url路由控制器
#但是当process_request里面return的是一个HttpResponse对象,那么后面的中间件的process_request将不再执行,也不会走到url路由控制器
#return HttpResponse('中间件md1的逻辑,没有通过!!!')
class Md2(MiddlewareMixin):
def process_request(self,request):
print('MD1--process_request')
views.py代码
def home(request):
print('home')
return render(request,'home.html')
执行流程--中间件正常return None的情况:
MD1--process_request
MD2--process_request
home
执行流程--中间件Md1中响应回复对象的情况:
MD1--process_request
因为Md1中return的是响应对象,所以就不会再向下执行了,同时也不会去执行逻辑代码。
- 2.process_response
class Md1(MiddlewareMixin):
def process_request(self,request):
print('MD1--process_request')
def process_response(self,request,response):
:param request: 当前请求对象
:param response: 视图函数的响应对象
:return:
print('Md1--响应')
#可以对响应内容做统一处理,如加响应头
response['xx'] = 'oo'
print(response.content) #获取响应回复内容 #b'ok'
#注意,如果你写了process_response方法,那么这个方法必须return response
return response
class Md2(MiddlewareMixin):
def process_request(self,request,response):
print('MD2--process_request')
def process_response(self,request,response):
print('MD2--响应')
# if response.content != b'ok':
#如果process_response方法里面return了一个HttpResponse对象,那么这个对象会覆盖视图返回来的HttpResponse对象
#return HttpResponse('响应不OK!!!')
return response
views.py文件
def home(request):
print('home')
return render(request,'home.html')
#return HttpResponse('我是home响应')
执行流程 正常执行:
MD1--process_request #中间件请求从上至下
MD2--process_request
home #请求结束会后执行视图逻辑
MD2--process_response #中间响应从下至上
MD1--process_response
执行流程 中间件HttpResponse响应覆盖视图返回来的Httpresponse对象:
MD1--process_request #中间件请求从上至下
MD2--process_request
home #执行视图逻辑,响应我是home响应
MD2--process_response #中间件响应从下至上,覆盖视图响应对象响应不OK!!!
MD1--process_response
- 注意事项
当中间件1的process_request方法return的是一个HttpResponse,那么会执行中间件1的process_response方法,不会去执行中间件2的方法了
- 3.process_view(self,request,view_func,view_args,view_kwargs)
from django.shortcuts import render,redirect,HttpResponse
from django.utils.deprecation import MiddlewareMix
class Md1(MiddlewareMixin):
def process_request(self,request):
print('MD1--process_request')
def process_response(self,request,response):
print('MD1--process_response')
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print('MD1--process_view')
class Md2(MiddlewareMixin):
def process_request(self,request):
print('MD2--process_request')
def process_response(self,request,response):
:param request:
:param view_func: 此次请求要执行的视图函数对象
:param view_args: 要函数的参数
:param view_kwargs: 要函数的参数
:return:
print('MD2--process_response')
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print('MD2--process_view')
执行流程:
MD1--process_request #中间件请求从上至下
MD2--process_request
MD1--process_view #中间件视图从上至下
MD2--process_view
中间件2执行函数名称 home
home #逻辑视图
MD2--process_response #中间件响应 从下至上
MD1--process_response
process_view图解
4.process_exception(self,request,exception)
当视图函数出现错误或者异常时,自动触发的方法,能够捕获视图出现的错误,进行一些错误的统一处理
from django.shortcuts import render,redirect,HttpResponse
from django.utils.deprecation import MiddlewareMixin
class Md1(MiddlewareMixin):
def process_request(self,request):
print('MD1--process_request')
def process_response(self,request,response):
print('MD1--process_response')
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print('MD1--process_view')
def process_exception(self,request,exception):
print('MD1--process_exception')
class Md2(MiddlewareMixin):
def process_request(self,request):
print('MD2--process_request')
def process_response(self,request,response):
print('MD2--process_response')
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print('MD2--process_view')
def process_exception(self,request,exception):
from django.core.exceptions import PermissionDenied
# print('>>>>>>', exception, type(exception))
# if isinstance(exception,PermissionDenied):
# return HttpResponse('权限不够!!!!!')
#>>>>>> 权限不够 <class 'django.core.exceptions.PermissionDenied'>
# >>>>>> 出错啦!!!
print('MD2--process_exception')
views.py代码
from django.core.exceptions import PermissionDenied #为了演示错误
def home(request):
print('home')
raise PermissionDenied('权限不够')
return render(request,'home.html')
执行流程:
MD1--process_request #中间件请求从上至下
MD2--process_request
MD1--process_view #中间件视图从上至下
MD2--process_view
home #逻辑视图
MD2--process_exception #中间件错误从下至上
MD1--process_exception
MD2--process_response #中间件响应从下至上
MD1--process_response
process_exception图解
5.process_template_response(self,request,reponse)
from django.shortcuts import render,redirect,HttpResponse
from django.utils.deprecation import MiddlewareMixin
class Md1(MiddlewareMixin):
def process_request(self,request):
print('MD1--process_request')
def process_response(self,request,response):
print('MD1--process_response')
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print('MD1--process_view')
def process_exception(self,request,exception):
print('MD1--process_view')
def process_template_response(self,request,response):
print('MD1--process_template_response')
return response
class Md2(MiddlewareMixin):
def process_request(self,request):
print('MD2--process_requeust')
def process_response(self,request,response):
print('MD2--process_response')
def process_view(self,request,view_func,view_args,view_kwargs):
print('MD2--process_view')
def process_exception(self,request,exception):
print('MD2--process_exception')
def process_template_response(self,request,response):
print('MD2--process_template_response')
return response
views.py代码
def home(request):
print('home')
def render():
print('你好render')
return HttpResponse('你好response')
ret = HttpResponse('ojbk')
#必须给HttpResponse对象封装一个render属性等于一个render函数,才能触发中间件里面的process_template_response方法
ret.render = render
return ret
执行流程:
MD1--process_request #中间件请求从上至下
MD2--process_request
MD1--process_view #中间件视图从上至下
MD2--process_view
home #视图逻辑
MD2--process_template_response #中间件模板 从下至上
MD1--process_template_response
你好render #视图逻辑里面的render()函数中响应对象
MD2--process_response #中间件响应 从下至上
MD1--process_response
总结下中间件执行流程
请求到达中间件之后,先按照正序执行每个注册中间件的process_reques方法,process_request方法返回的值是None,
就依次执行,如果返回的值是HttpResponse对象,不再执行后面的process_request方法,而是执行当前对应中间件的process_response方法,
将HttpResponse对象返回给浏览器。也就是说:如果MIDDLEWARE中注册了6个中间件,执行过程中,第3个中间件返回了一个HttpResponse对象,
那么第4,5,6中间件的process_request和process_response方法都不执行,顺序执行3,2,1中间件的process_response方法。
process_request方法都执行完后,匹配路由,找到要执行的视图函数,先不执行视图函数,先执行中间件中的process_view方法,
process_view方法返回None,继续按顺序执行,所有process_view方法执行完后执行视图函数。加入中间件3 的process_view方法返回了HttpResponse对象,
则4,5,6的process_view以及视图函数都不执行,直接从最后一个中间件,也就是中间件6的process_response方法开始倒序执行。
url路由系统补充---include路由分发和命名空间 namespace
- 1.创建app
python manage.py startapp app01
- 2.配置app,在settings.py文件中
INSTALLED_APPS = [
...
'app02',
]
路由分发步骤
- 1.在项目主目录下的urls.py(以后我们称之为总路由)文件中,写上如下内容
from django.conf.urls import url,inclue
from django.contrib import admin
#路由分发功能
urlpatterns = [
url(r'^admin/',admin.site.urls),
url(r'^app01/',include('app01.urls')),#include参数格式'应用名称.urls'
url(r'^app02/',include('appo2.urls')),
#/app01/index/ 先在总路由中匹配前面的路径,然后匹配到了,拿剩下的index/,去app01应用下面的urls.py文件进行路径匹配
]
- 2.在每个应用文件夹下面创建一个ursl.py文件,里面内容
from django.conf.urls import url,include
from app01 import views
urlpatterns = [
url(r'^index/',views.index),
]
问题,当两个应用中的url的别名相同了,使用反向解析的时候该怎么解决
app01的urls.py
from django.conf.urls import url,include
from app01 import views
urlpatterns = [
url(r'^index/',views.index),
url(r'^home/',views.home,name='home'),
]
app02下的urls.py
from django.conf.urls import url,include
from app02 import views
urlpatterns = [
url(r'^index/',views.index),
url(r'^home/',views.home,name='home'),
]
app01的views.py文件进行别名解析
def index(request):
print('app01>>>',reverse('home'))
return HttpResponse('app01-index')
app02的views.py文件进行别名解析
def index(request):
print('app02>>>',reverse('home'))
return HttpResponse('app02-index')
以上执行完后,发现别名冲突,导致反向解析出错了
解决办法,用命名空间
总路由写法
from django.conf.urls import url,include
from django.contrib import admin
#路由分发
urlpatterns = [
url(r'^app01/',include('app01.urls',namespace='app01')),
url(r'^app02/',include('app02.urls',namespace='app02')),
]
app01视图写法
def index(request):
print('app01>>>',reverse('app01:home'))
return HttpResponse('app01-index')
app02视图写法
def index(request):
print('app02>>',reverse('app02:home'))
return HttpResponse('app02-index')
模板中使用
{% url 'app01:home' %}
路由分发如何设置首页
如果我们想通过输入http://127.0.0.1:8000/app01/,看到app01这个应用的首页,怎么办?就像现在输入一个http://127.0.0.1:8000来查看网站的首页,怎么办?
url(r'^$', views.index),#以空开头,还要以空结尾,写在项目的urls.py文件里面就是项目的首页,写在应用文件夹里面的urls.py文件中,那就是app01的首页
整个完整请求-中间件-后台逻辑处理的过程
django学习第十三天--自定义中间件的更多相关文章
- Django学习笔记(15)——中间件
当Django处理一个Request的过程是首先通过中间件,然后再通过默认的URL方式进行的.我们可以在Middleware这个地方把所有Request拦截住,用我们自己的方式完成处理以后直接返回Re ...
- Django学习之十三:提高页面开发效率减少冗余的模板系统
目录 Django 模板 模板语法 逻辑语法 函数式过滤器 内置filter 功能tag 注释 内置tag 导入三方tag and filter(load) 过滤器和功能tag的区别 自定义tag和f ...
- Django 学习第五天——自定义过滤器及标签
代码布局:(自定义的代码放在哪?) 1.创建某个 app 特有的: 在 app 目录下,创建 templatetags python包(文件夹): 再到 templatetags 文件夹下创建pyth ...
- 潭州课堂25班:Ph201805201 django框架 第十三课 自定义404页面,auth系统中的User模型,auth系统权限管理 (课堂笔记)
当 DEBUG=True 时,django 内部的404报错信息, 自带的报错信息, 要自定义404信息,要先把 DEBUG=False , 之后要自定义4040页面,有两种方法, 方法1,在创建40 ...
- 【转】MYSQL入门学习之十三:自定义函数的基本操作
转载地址:http://www.2cto.com/database/201212/177382.html 一.自定义函数(UDF)的特性和功能 www.2cto.com 函数能分 ...
- (28)django的中间件(自定义中间件和防范跨站请求伪造攻击)-重要的概念
Django中间件和中间件不是同一种东西 什么是中间件:中间件是一个很大的概念,只要程序和程序之间还有一层程序,用来处理两个程序的整个交互过程的请求.数据等等就叫中间件 Django中间件:是介于re ...
- {Django基础九之中间件} 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证
Django基础九之中间件 本节目录 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证 六 xxx 七 xxx 八 xxx 一 前戏 我们在前面的课程中已经学会了 ...
- Django学习笔记之Django中间件
准备 我们在前面的课程中已经学会了给视图函数加装饰器来判断是用户是否登录,把没有登录的用户请求跳转到登录页面.我们通过给几个特定视图函数加装饰器实现了这个需求.但是以后添加的视图函数可能也需要加上装饰 ...
- Django学习之七:Django 中间件
目录 Django 中间件 自定义中间件 - - - 大体两种方式 将中间件移除 实例 中间件加载源码阅读 总结 Django 中间件 Tips: 更新日志: 2019.01.31 更新django中 ...
- Django学习笔记之上下文处理器和中间件
上下文处理器 上下文处理器是可以返回一些数据,在全局模板中都可以使用.比如登录后的用户信息,在很多页面中都需要使用,那么我们可以放在上下文处理器中,就没有必要在每个视图函数中都返回这个对象. 在set ...
随机推荐
- [转帖]Linux命令学习手册-readelf
https://www.jianshu.com/p/405844abefae readelf elf-file(s) 功能 用于显示 elf 格式文件的信息. 描述 readelf 用来显示一个或者多 ...
- [转帖]ELF文件详解
一.ELF概述 1.ELF的定义 ELF(Executable and Linkable Format)文件是一种目标文件格式,常见的ELF格式文件包括:可执行文件.可重定位文件(.o).共享目标文件 ...
- overcommit_memory的简单学习
overcommit_memory的简单学习 背景 前几天一个测试环境启动失败. 总是有如下的提示: Native memory allocation (mmap) failed to map 122 ...
- Windows设置一键安装Mysql数据库的方法
Windows设置一键安装Mysql数据库的方法 前言 因为MySQL数据库的8126 65536 以及3072最大索引长度等问题 研发这边提交的补丁总是出现稀奇古怪的问题. mysql数据库又因为D ...
- 将自签名创建的ca证书 添加到linux的授信证书列表的办法
第一步: 将ca 证书 从cert 格式转换成pem格式 openssl x509 -in ca.crt -out ca.pem -outform PE 第二步: 将ca 证书导入至系统中来 cat ...
- justify-content: space-between能够对齐的解决办法
解决办法一 .main{ display: flex; justify-content: space-around; flex-wrap: wrap; } .son{ width:100px } // ...
- axios发送请求时携带token
请求头携带token async getUserlist(){ // 需要授权的Api,必须在青丘头中使用Authorization 字段提供token令牌 const AUTH_TOKEN=loca ...
- k8s笔记——NodePort暴露nginx-controller实现https自动跳转自定义nodePort端口
安装nginx-controller并暴露nodePort helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx ...
- SqlSugar Code First
注意点 1.SqlSugar Code First可以快速开发,使用起来也要分阶段使用,比如早期随便搞,中后期需要禁用一些功能保证数据安全(标题6和7 ) 2.数据库账号需要有比较高的权限, 3. ...
- 【译】命名变得简单:AI 支持的重命名建议
您是否曾经为命名一个变量.方法或类而挣扎过?找到表达性和简洁性之间的完美平衡了吗?您并不孤单.我们通过 GitHub Copilot Chat 扩展(需要订阅)在最新的 Visual Studio 预 ...