中间件------------------------>>>>>>>>>>>>>
中间件是一个用来处理django的响应与请求的框架级别的钩子.它是一个轻量,低级别的插件系统,
用于在全局范围内改变django的输入和输出,每个中间件组件都负责做一些特定的功能. ----简单来说,Django的中间件是一个类。用来在全局范围内处理请求和响应。 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
1. 执行时间
在视图函数之前执行
2. 参数
request 和视图中的request是同一个
3. 返回值
返回None
返回response对象
不执行后面中间的process_request方法和视图
直接执行当前值中间件的process_response方法
4. 执行顺序
按照注册的顺序执行 2. process_response
1. 执行时间
在视图函数之后执行
2. request, response
request 和视图中的request是同一个
response 返回的response对象
3. 返回值
返回response对象
4. 执行顺序
按照注册的倒序执行 3. process_view
1. 执行时间
在视图函数之前,process_request之后执行
2. 参数
view_func 将要执行的视图函数
view_args 视图函数的可变长位置参数
view_kwargs 视图函数的可变长关键字参数
3. 返回值
返回 None 正常执行
返回 response对象 不执行后面的process_view和视图,直接执行所有中间件的process_response方法 4。执行顺序
按照注册的顺序执行 4. process_exception(有条件触发:有错误才执行)
1. 执行时间
在视图函数之后,process_response之前执行
2. 参数
exception 错误对象
3. 返回值
返回 None 不对错误进行处理,交给下一个中间件进行处理
返回 response对象 下一个中间的process_exception不执行,直接执行所有中间件的process_response方法
4. 执行顺序
按照注册的倒序执行
5. process_template_response(条件触发:视图返回的response有render方法)
1. 执行时间
在视图函数之后,process_response之前执行
2. 参数
3. 返回值
返回 response对象
4. 执行顺序
按照注册的倒序执行,执行完所有的process_template_response方法后执行response.render方法

                        中间件的执行流程                           

上一部分,我们了解了中间件中的5个方法,它们的参数、返回值以及什么时候执行,现在总结一下中间件的执行流程。

请求到达中间件之后,先按照正序执行每个注册中间件的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方法开始倒序执行。

process_template_response和process_exception两个方法的触发是有条件的,执行顺序也是倒序。总结所有的执行流程如下:

小练习:

(1)

AuthMD中间件注册后,所有的请求都要走AuthMD的process_request方法。

如果URL在黑名单中,则返回This is an illegal URL的字符串;

访问的URL在白名单内或者session中有user用户名,则不做阻拦走正常流程;

正常的URL但是需要登录后访问,让浏览器跳转到登录页面。

注:AuthMD中间件中需要session,所以AuthMD注册的位置要在session中间的下方。

from django.conf.urls import url
from django.contrib import admin
from app01 import views urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/',views.login),
url(r'^home/',views.home),
url(r'^index/',views.index),
url(r'^logout/',views.logout),
]

urls

from django.shortcuts import render,HttpResponse,redirect
from django.conf import global_settings
# Create your views here. def login(request):
err_msg = ""
if request.method == "POST":
name = request.POST.get("name")
pwd = request.POST.get("pwd")
if name == "alex" and pwd == "":
request.session['user'] = "user"
# request.session.set_expiry(0) #设置关闭浏览器后自动注销
return_path = request.GET.get("return","")
if return_path:
return redirect(return_path)
else:
return redirect("/home/") else:
err_msg = "用户名或者密码错误"
return render(request,"login.html",{"err_msg":err_msg}) # 登陆装饰器
# def wrap(func):
# def inner(request,*args,**kwargs):
# if request.session.get("is_login","") == "True":
# ret = func(request,*args,**kwargs)
# return ret
# else:
# path = request.path_info
# return redirect("/login/?return={}".format(path))
# return inner # @wrap
def home(request):
return render(request,"home.html") # @wrap
def index(request):
return render(request,"index.html") def logout(request):
del request.session['user']
return redirect("/login/")

Views文件

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect, render class Login_middle(MiddlewareMixin):
white_list = ["/login/", ]
black_list = ["/black/", ] def process_request(self, request):
path = request.path_info
if path in self.black_list:
return HttpResponse("这是黑名单的网址")
elif path in self.white_list or request.session.get("user"):
print(11)
return
else:
print(22)
return redirect("/login/?return={}".format(path))

中间件

'app01.my_middlewaremixin.Login_middle'

settings注册中间件

#login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
<p>用户名:<input type="text" name="name"></p>
<p>密码:<input type="password" name="pwd"></p>
<p><button>提交</button></p><span>{{ err_msg }}</span>
</form>
</body>
</html> #index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>欢迎登陆index页面</h1>
</body>
</html> #home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>欢迎登陆home页面</h1>
<a href="/logout/">注销</a>
</body>
</html>

template文件 (三个)

(2) 限制访问频率,一分钟只能访问3次.
    思路:根据IP做判断,1分钟只能访问3次
          1. 获取ip
          2. 记录时间
          3. 根据访问记录做判断

import time

l = {}
class Throttle(MiddlewareMixin):
def process_request(self, request): ip = request.META.get("REMOTE_ADDR")
now = time.time()
if not l.get(ip, ""):
l[ip] = []
history = l[ip]
x = []
for i in history:
if now - i < 5:
x.append(i)
print(x)
history = x
print(history)
if len(history) >= 3:
return HttpResponse("次数太多了")
history.insert(0, now)
l[ip] = history

中间件代码

request.META 可以获取到所有内容,可以从中找你想用的东西.一组组键值对儿
# {'ALLUSERSPROFILE': 'C:\\ProgramData',
# 'APPDATA': 'C:\\Users\\zhanghutao\\AppData\\Roaming',
# 'COMMONPROGRAMFILES': 'C:\\Program Files\\Common Files',
# 'COMMONPROGRAMFILES(X86)': 'C:\\Program Files (x86)\\Common Files',
# 'COMMONPROGRAMW6432': 'C:\\Program Files\\Common Files',
# 'COMPUTERNAME': 'DESKTOP-30PDHUE',
# 'COMSPEC': 'C:\\WINDOWS\\system32\\cmd.exe',
# 'DJANGO_SETTINGS_MODULE': '中间件.settings',
# 'HOMEDRIVE': 'C:', 'HOMEPATH': '\\Users\\zhanghutao',
# 'LOCALAPPDATA': 'C:\\Users\\zhanghutao\\AppData\\Local',
# 'LOGONSERVER': '\\\\DESKTOP-30PDHUE',
# 'MOZ_PLUGIN_PATH': 'E:\\Foxit Reader\\plugins\\',
# 'NUMBER_OF_PROCESSORS': '4',
# 'ONEDRIVE': 'C:\\Users\\zhanghutao\\OneDrive',
# 'OS': 'Windows_NT',
# 'PATH': 'C:\\WINDOWS\\system32;'
# 'C:\\WINDOWS;'
# 'C:\\WINDOWS\\System32\\Wbem;'
# 'C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;'
# 'C:\\Program Files\\WIDCOMM\\Bluetooth Software\\;C:\\Program Files\\WIDCOMM\\Bluetooth Software\\syswow64;D:\\mysql\\mysql-5.7.23-winx64\\bin;;D:\\PPB\\PBB Reader\\x64;D:\\python3.6\\Scripts\\;D:\\python3.6\\;C:\\Users\\zhanghutao\\AppData\\Local\\Microsoft\\WindowsApps;;D:\\python3.6\\lib\\site-packages\\pywin32_system32;D:\\python3.6\\lib\\site-packages\\pywin32_system32', 'PATHEXT': '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC', 'PROCESSOR_ARCHITECTURE': 'AMD64', 'PROCESSOR_IDENTIFIER': 'Intel64 Family 6 Model 58 Stepping 9, GenuineIntel', 'PROCESSOR_LEVEL': '6', 'PROCESSOR_REVISION': '3a09', 'PROGRAMDATA': 'C:\\ProgramData', 'PROGRAMFILES': 'C:\\Program Files', 'PROGRAMFILES(X86)': 'C:\\Program Files (x86)', 'PROGRAMW6432': 'C:\\Program Files', 'PSMODULEPATH': 'C:\\Program Files\\WindowsPowerShell\\Modules;C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\Modules;C:\\Program Files\\Intel\\Wired Networking\\', 'PUBLIC': 'C:\\Users\\Public', 'PYCHARM_HOSTED': '1', 'PYCHARM_MATPLOTLIB_PORT': '54693', 'PYTHONIOENCODING': 'UTF-8', 'PYTHONPATH': 'D:\\pycharm\\PyCharm 2018.1.3\\helpers\\pycharm_matplotlib_backend;D:\\PythonTest\\django项目\\中间件', 'PYTHONUNBUFFERED': '1', 'SESSIONNAME': 'Console', 'SYSTEMDRIVE': 'C:', 'SYSTEMROOT': 'C:\\WINDOWS', 'TEMP': 'C:\\Users\\ZHANGH~1\\AppData\\Local\\Temp', 'TMP': 'C:\\Users\\ZHANGH~1\\AppData\\Local\\Temp', 'USERDOMAIN': 'DESKTOP-30PDHUE', 'USERDOMAIN_ROAMINGPROFILE': 'DESKTOP-30PDHUE', 'USERNAME': 'zhanghutao', 'USERPROFILE': 'C:\\Users\\zhanghutao', 'WINDIR': 'C:\\WINDOWS', 'RUN_MAIN': 'true', 'SERVER_NAME': 'DESKTOP-30PDHUE', 'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_PORT': '8000', 'REMOTE_HOST': '', 'CONTENT_LENGTH': '', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'WSGIServer/0.2', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/index/', 'QUERY_STRING': '',
# 'REMOTE_ADDR': '127.0.0.1',
# 'CONTENT_TYPE': 'text/plain',
# 'HTTP_HOST': '127.0.0.1:8000',
# 'HTTP_CONNECTION': 'keep-alive', 'HTTP_UPGRADE_INSECURE_REQUESTS': '1', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36', 'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9', 'HTTP_COOKIE': 'csrftoken=HSERiDbpYwWLfLhrjDIgcsMP8HjD1CqXuSPjgSD40l8YpqbMPTYaNKl3xm6MLWne; sessionid=qfrad5a76h2ozt0erj74wef1nrzsl63n', 'wsgi.input': <_io.BufferedReader name=964>, 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>, 'CSRF_COOKIE': 'HSERiDbpYwWLfLhrjDIgcsMP8HjD1CqXuSPjgSD40l8YpqbMPTYaNKl3xm6MLWne'}

例如:

python 终极篇 ---- 中间件的更多相关文章

  1. python 终极篇 --- django 视图系统

    Django的View(视图) 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错误, ...

  2. python终极篇 --- django 初识

    1. 下载: 命令行: pip install django==1.11.15 pip install -i 源 django==1.11.15 pycharm settings 解释器 点+号 输入 ...

  3. python 终极篇 ---django 认证

    Django自带的用户认证 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Djang ...

  4. python 终极篇 --- form组件 与 modelForm

                                                           form组件                                       ...

  5. python 终极篇 --- django 路由系统

                          URL配置                        基本格式: from django.conf.urls import url urlpattern ...

  6. python终极篇 ---django 模板系统

                                                模板系统                                                . MV ...

  7. python 终极篇 cookie与session

    ()cookie与session---------->>>>>>>>>>>>>>>>>>&g ...

  8. python终极篇 --- django---班级管理系统

    周末没事自己写了个班级管理系统,虽然简单,但也算个前期学习的总结吧 from django.db import models # Create your models here. class Banj ...

  9. 【Python五篇慢慢弹】快速上手学python

    快速上手学python 作者:白宁超 2016年10月4日19:59:39 摘要:python语言俨然不算新技术,七八年前甚至更早已有很多人研习,只是没有现在流行罢了.之所以当下如此盛行,我想肯定是多 ...

随机推荐

  1. GetSystemMetrics()函数的用法 转

    转自 http://www.cnblogs.com/lidabo/archive/2012/07/10/2584725.html 可以用GetSystemMetrics函数可以获取系统分辨率,但这只是 ...

  2. Jquery 操作 select 的操作指南

    这里我们以一个简单的select作为原型来进行说明: <select> <option value="a1">香蕉1</option> < ...

  3. thinkphp 利用GD库在图片上写文字

    <?php /** * Created by PhpStorm. * User: Administrator */ namespace Home\Event; use \Think\Image; ...

  4. 编程界失传秘术,SSO单点登录,什么是单点,如何实现登录?

    单点登录 多系统,单一位置登录,实现多系统同时登录的一种技术. 常出现在互联网应用和企业级平台中. 如:京东. 单点登录一般是用于互相授信的系统,实现单一位置登录,全系统有效的. 三方登录:某系统,使 ...

  5. 06 day小数据池

    1.小数据池,id() 小数据池针对的是: int ,str,bool-----都是不可变的数据类型  a.int 类型 a = 1000 b = 1000 print(id(a), id(b))   ...

  6. Linux内核调用SPI平台级驱动_实现OLED的显示功能

    Linux内核调用SPI驱动_实现OLED显示功能 0. 导语 进入Linux的世界,发现真的是无比的有趣,也发现搞Linux驱动从底层嵌入式搞起真的是很有益处.我们在单片机.DSP这些无操作系统的裸 ...

  7. python之内存与编码的那点事

    一.初始编码 ASCII 码不支持中文 是py2版本中的默认编码 ​Unicode 万国码, 英文使用16位(即两个字节​),中文使用32位(四个字节) ​utf-8 美国最少使用八位(1字节), 欧 ...

  8. 20154327 Exp1 PC平台逆向破解

    一.实践目标 1.运行原本不可访问的代码片段 2.强行修改程序执行流 3.以及注入运行任意代码 二.基础知识 1.直接修改程序机器指令,改变程序执行流程 2.通过构造输入参数,造成BOF攻击,改变程序 ...

  9. BZOJ1433_假期的宿舍_KEY

    题目传送门 二分图匹配的题目. 但建边有一定难度,关系比较复杂. 首先要统计总共需要几张床. 在校且住校的会需要一张床,不住校的需要一张床. 然后对于在校且住校的与自己的床连边,不住校的与认识的住校的 ...

  10. 优步UBER司机全国各地奖励政策汇总 (3月21日-3月27日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...