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>

浙公网安备 33010602011771号