day87---django的中间件

1. Django的中间件

django中的中间件(middleware)是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出在django中。中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。对所有请求或一部分请求做批量处理时,可以使用中间件来实现

在django中叫中间件,在其他的框架中有的叫管道(httphandle)

在django项目的settings模块中,有一个MIDDLEWARE_CLASSES变量,其中每一个元素就是一个中间件

django自带的中间件

django自带七个中间件,自上到下依次执行,顺序不能混乱(如果需要自定义中间件,一定要写在这些中间件下面来加载)

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]

中间件的方法

中间件中一共有五个方法:

  • process_request

  • process_view

  • process_exception

  • process_response

  • process_template_response

2. 中间件之process_request和process_response

描述

  • 当用户发起请求的时候会依次经过所有的的中间件,这个时候的请求时process_request,最后到达views的函数中,views函数处理后,在依次穿过中间件,这个时候是process_response,最后返回给请求者

  • process_request可以没有返回值,但是process_response必须要有返回值

  • 如果在process_request时有return返回值,则直接在当前中间件中断,不再继续往下走,直接以倒序的方式运行process_response,最后返回给请求者

-#### 执行顺序流程:
- ##### 用户发起请求
- ##### 从依次穿到所有中间件的process_request
- ##### 加载url路由系统进行url分发
- ##### 加载views视图系统进行数据处理
- ##### 加载models模型系统进行数据的读写
- ##### 加载template模板系统进行模版渲染
- ##### 从倒序穿过所有中间件的process_response
- ##### 返回信息给用户

应用

    # settings.py
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'app01.middleware.custom.M1',
        'app01.middleware.custom.M2',
    ]
    #
    # middleware/custom.py
    from django.utils.deprecation import MiddlewareMixin
    class M1(MiddlewareMixin):
        def process_request(self, request):
            print('M1---请求')
        def process_response(self, request, response):
            print('M1---响应')
            return response
    class M2(MiddlewareMixin):
        def process_request(self, request):
            print('M2+++请求')
        def process_response(self, request, response):
            print('M2+++响应')
            return response
    #
    # views.py
    from django.shortcuts import HttpResponse
    def index(request):
        print('执行视图函数...')
        return HttpResponse('ok')
    #### 执行结果 >>>
    M1---请求
    M2+++请求
    执行视图函数...
    M2+++响应
    M1---响应

3. 中间件之process_view

描述

django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
  • 当最后一个中间的process_request到达路由关系映射之后,返回到中间件1的process_view,然后依次往下,到达views函数,最后通过process_response依次返回到达用户

  • 如果在process_view时有return返回值,则直接在当前中间件中断,不再继续往下走,越过所有的process_view和views视图函数,直接以倒序的方式运行process_response,最后返回给请求者

  • 执行顺序流程:

    • 用户发起请求
    • 依次穿到所有中间件的process_request
    • 加载url路由系统进行url分发
    • 依次穿到所有中间件的process_view
    • 加载views视图系统进行数据处理
    • 加载models模型系统进行数据的读写
    • 加载template模板系统进行模版渲染
    • 倒序穿过所有中间件的process_response
    • 返回信息给用户

应用

    # settings.py
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'app01.middleware.custom.M1',
        'app01.middleware.custom.M2',
    ]
    #
    # middleware/custom.py
    from django.utils.deprecation import MiddlewareMixin
    class M1(MiddlewareMixin):
        def process_request(self, request):
            print('M1---请求')
        def process_view(self, request, callback, callback_args, callback_kwargs):
            print("M1---view...")
        def process_response(self, request, response):
            print('M1---响应')
            return response
    class M2(MiddlewareMixin):
        def process_request(self, request):
            print('M2+++请求')
        def process_view(self, request, callback, callback_args, callback_kwargs):
            print("M2+++view...")
        def process_response(self, request, response):
            print('M2+++响应')
            return response
    #
    # views.py
    from django.shortcuts import HttpResponse
    def index(request):
        print('执行视图函数...')
        return HttpResponse('ok')
    #### 执行结果 >>>
    M1---请求
    M2+++请求
    M1---view...
    M2+++view...
    执行视图函数...
    M2+++响应
    M1---响应

4. 中间件之process_exception

描述

process_exception(self, request, exception)
  • 执行process_request到到达urls路由分发后继续执行完process_view方法,就到了执行视图函数。当views的函数中出现错误时,会以倒叙的方式执行process_exception方法,找到匹配到的错误信息。如果匹配到就以倒序的方式运行process_response,最后返回给请求者,如果没有匹配到则直接在页面显示错误信息。没有错误则不会运行process_exception方法,直接以倒序的方式运行process_response,最后返回给请求者

  • 执行顺序流程:

    • 用户发起请求
    • 依次穿过所有中间件的process_request
    • 加载url路由系统进行url分发
    • 依次穿过所有中间件的process_view
    • 加载views视图系统进行数据处理
    • 加载models模型系统进行数据的读写
    • 加载template模板系统进行模版渲染
    • 当views视图系统错误时,从依次穿过所有中间件的process_exception
    • 倒序穿过所有中间件的process_response
    • 返回信息给用户

应用

    # settings.py
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'app01.middleware.custom.M1',
        'app01.middleware.custom.M2',
    ]
    #
    # middleware/custom.py
    from django.utils.deprecation import MiddlewareMixin
    class M1(MiddlewareMixin):
        def process_request(self, request):
            print('M1---请求')
        def process_view(self, request, callback, callback_args, callback_kwargs):
            print("M1---view...")
        def process_exception(self, request, exception):
            print("M1---exception...")
        def process_response(self, request, response):
            print('M1---响应')
            return response
    class M2(MiddlewareMixin):
        def process_request(self, request):
            print('M2+++请求')
        def process_view(self, request, callback, callback_args, callback_kwargs):
            print("M2+++view...")
        def process_exception(self, request, exception):
            print("M2+++exception...")
        def process_response(self, request, response):
            print('M2+++响应')
            return response
    #
    # views.py
    from django.shortcuts import HttpResponse
    def index(request):
        print('执行视图函数...')
        print(yy)
        return HttpResponse('ok')
    #### 执行结果 >>>
    M1---请求
    M2+++请求
    M1---view...
    M2+++view...
    执行视图函数...
    M2+++exception...
    M1---exception...
    M2+++响应
    M1---响应

5. 中间件之process_template_response

process_template_response(self,request,response)

只有当views函数中返回的对象中具有render方法,会被调用process_template_response

6. Pillow模块介绍

安装Pillow模块

pip install Pillow

基本使用

  • 创建图片对象:Image.new(mode, size, color=0)

    • mode:指定图片的模式(常用RGB模式)
    • size:指定图片的尺寸大小(width, height)
    • color:指定图片的颜色(R,G,B)
  • 创建画笔对象(用于在图片上画任意内容):ImageDraw.Draw(im, mode=None)

    • im:指定一块画布(指定图片对象)
    • mode:指定图片的模式(不指定则为图片对象的模式)
  • 创建字体对象:ImageFont.truetype(font=None, size=10, index=0, encoding="", layout_engine=None)

    • font:指定字体文件路径
    • size:指定字体大小
    • index:指定要加载哪个字体(默认是第一个可用的字体)
    • encoding:指定字体的编码
    • layout_engine:指定布局的引擎

画笔使用

  • 画点point(self, xy, fill=None):xy表示坐标,fill表示颜色

    img_obj = Image.new(mode='RGB', size=(120, 80), color=(255, 255, 255))
    draw_obj = ImageDraw.Draw(img_obj)
    draw_obj.point([100, 100], fill='red')
    draw.point([300, 300], fill=(255, 255, 255))
  • 画线line(self, xy, fill=None, width=0):xy表示开始坐标和结束坐标,fill表示颜色,width表示线宽

    img_obj = Image.new(mode='RGB', size=(120, 80), color=(255, 255, 255))
    draw_obj = ImageDraw.Draw(img_obj)
    draw_obj.line((100,100,100,300), fill='red')
    draw_obj.line((100,100,300,100), fill=(255, 255, 255))
  • 画圆arc(self, xy, start, end, fill=None):xy表示开始坐标和结束坐标(圆要画在其中间),start表示开始角度,end表示结束角度,fill表示颜色

    img_obj = Image.new(mode='RGB', size=(120, 80), color=(255, 255, 255))
    draw_obj = ImageDraw.Draw(img_obj)
    draw_obj.arc((100,100,300,300),0,90,fill="red")
  • 写文本text(self, xy, text, fill=None, font=None, anchor=None, *args, **kwargs):xy表示开始坐标和结束坐标,text表示写入的内容,fill表示颜色,font指定字体的对象

    img_obj = Image.new(mode='RGB', size=(120, 80), color=(255, 255, 255))
    draw_obj = ImageDraw.Draw(img_obj)
    draw_obj.text([0, 0], 'linux', "red")
  • 特殊字体文字:使用写文本的方式,加载其他的字体文件

    img_obj = Image.new(mode='RGB', size=(120, 80), color=(255, 255, 255))
    draw_obj = ImageDraw.Draw(img_obj)
    font_obj = ImageFont.truetype('static/fonts/verification.ttf', size=60)
    draw_obj.text([0, 0], 'linux', "red", font=font_obj)

添加图片滤镜效果

filter(ImageFilter.EDGE_ENHANCE_MORE)

  • ImageFilter.BLUR:模糊滤镜

  • ImageFilter.CONTOUR:轮廓滤镜

  • ImageFilter.EDGE_ENHANCE:边界加强

  • ImageFilter.EDGE_ENHANCE_MORE:边界加强(阀值更大)

  • ImageFilter.EMBOSS:浮雕滤镜

  • ImageFilter.FIND_EDGES:边界滤镜

  • ImageFilter.SMOOTH:平滑滤镜

  • ImageFilter.SMOOTH_MORE:平滑滤镜(阀值更大)

  • ImageFilter.SHARPEN:锐化滤镜

把图片对象写入内存

    from io import BytesIO
    # 导入模块
    io_obj = BytesIO()
    # 实例化内存对象
    img_obj.save(io_obj, 'png')
    # 把图片对象写入到内存中
    data = io_obj.getvalue()
    # 从内存中读取出数据

7. 页面验证码刷新功能

验证码的点击刷新功能,只需要在img标签的src属性值后加上一个问号即可

    <img src="/vcode/" id="img_code" width="220" height="50">
    <script>
        $("#img_code").click(function () {
                $(this)[0].src += "?";
        });
    <script>

8. 生成随机验证码

配置路由器系统(urls.py)

    from django.conf.urls import url
    from app01 import views
    urlpatterns = [
        url(r'^login/$', views.login),
        url(r'^get_verification_code/$', views.get_verification_code),
    ]

配置随机验证码(utils/random_code.py)

	from PIL import Image, ImageDraw, ImageFont, ImageFilter
	import random
	from io import BytesIO
	class VerificationCode:
		def __init__(self, width=120, height=80, char_length=4, font_file='static/fonts/verification.ttf', font_size=60):
			self.width = width
			self.height = height
			self.char_length = char_length
			self.font_file = font_file
			self.font_size = font_size
		@staticmethod
		def random_color():
			return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
		@staticmethod
		def random_letter(start, end):
			return chr(random.randint(start, end))
		def build_code(self):
			# 实例化图片对象,指定颜色模式、图片大小、图片颜色
			img_obj = Image.new(mode='RGB', size=(self.width, self.height), color=self.random_color())
			# 给图片加滤镜
			img_obj = img_obj.filter(ImageFilter.BLUR)
			# 实例化画笔对象
			draw_obj = ImageDraw.Draw(img_obj)
			# 实例化字体对象,指定字体文件和大小
			font_obj = ImageFont.truetype(self.font_file, size=self.font_size)
			code_str = ''
			for i in range(self.char_length):
				# 随机生成一个数字或字母的字符
				random_chr = random.choice([str(random.randint(0, 9)), self.random_letter(65, 90), self.random_letter(97, 122)])
				# 写文字到图片上
				draw_obj.text((i * 30, 15), random_chr, self.random_color(), font=font_obj)
				# 把生成的随机字符记录到字符串变量中
				code_str += random_chr
			# 创建内存对象,开辟一块内存空间
			io_obj = BytesIO()
			# 把图片对象保存到内存中,并指定图片的格式
			img_obj.save(io_obj, 'png')
			# 从内存中把取出图片
			data = io_obj.getvalue()
			# 返回图片数据和随机字符串变量
			return data, code_str

配置视图函数(views.py)

	from django.shortcuts import render, HttpResponse
	from utils.random_code import VerificationCode
	def login(request):
		if request.method == 'POST':
			# user = request.POST.get('user')
			# pwd = request.POST.get('pwd')
			# 验证用户名密码略...
			code = request.POST.get('code')
			# 获取session中的随机字符串
			code_str = request.session.get('code_str')
			# 判断验证码
			if code.lower() != code_str.lower():
				return HttpResponse('验证码错误')
		return render(request, 'login.html')
	def get_verification_code(request):
		# 实例化验证码对象
		code_obj = VerificationCode()
		# 获取图片数据
		data = code_obj.build_code()
		# 把图片中记录的随机字符串写入session
		request.session['code_str'] = data[1]
		return HttpResponse(data[0])

配置模板页面(login.html)

	<!DOCTYPE html>
	<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
		<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
		<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
		<title>登录页面</title>
	</head>
	<body>
	<div class="container">
		<div class="row">
			<div class="col-md-offset-3 col-md-8">
				<div class="page-header">
					<h1>
						登录页面
						<small>login</small>
					</h1>
				</div>
				<form class="form-horizontal" action="/login/" method="post" enctype="multipart/form-data">
					{% csrf_token %}
					<div class="form-group">
						<label for="user" class="col-md-2 control-label">用户名:</label>
						<div class="col-md-6">
							<input type="text" class="form-control" id="user" name="user" placeholder="用户名">
						</div>
					</div>
					<div class="form-group">
						<label for="pwd" class="col-md-2 control-label">密码:</label>
						<div class="col-md-6">
							<input type="password" class="form-control" id="pwd" name="pwd" placeholder="密码">
						</div>
					</div>
					<div class="form-group">
						<label for="verification_code" class="col-md-2 control-label">验证码:</label>
						<div class="col-md-3">
							<input type="password" class="form-control" id="verification_code" name="code" placeholder="验证码">
						</div>
						<div class="col-md-3">
							<img src="/get_verification_code/" id="img_code" alt="随机验证码" width="165" height="33">
						</div>
					</div>
					<div class="form-group">
						<div class="col-md-offset-2 col-md-10">
							<div class="checkbox">
								<label>
									<input type="checkbox">记住我
								</label>
							</div>
						</div>
					</div>
					<p class="col-md-offset-3 err_msg"></p>
					<div class="form-group">
						<div class="col-md-offset-2 col-md-5">
							<input type="submit" id="login" class="btn btn-primary btn-block" value="登录">
						</div>
					</div>
				</form>
			</div>
		</div>
	</div>
	<script>
		$("#img_code").click(function () {
			$(this)[0].src += "?";
		});
	</script>
	</body>
	</html>
posted @ 2018-03-01 13:38  _岩哥  阅读(103)  评论(0)    收藏  举报