网上有很多文章都讲过这个话题,但是我确实在这里想要重新记录下,以前的自定义中间件方法在未来都会被遗弃,但是新的中间件确实值得学习(虽然我不认为现在的自定义中间件方法会比即将遗弃的好,捂脸!!),注意我不想系统的一步一步说,毕竟你们也能从网上找到!
中间件模板大概如下:
#函数方式定义中间件
def simple_middleware(get_response):
# 服务器第一次启动时候就执行一次之后不再执行的代码
def middleware(request):
# 视图函数执行之前的代码
response = get_response(request)
# 视图函数执行之后的代码
return response
return middleware
#类方式定义中间件
class middleware:
def __init__(self,get_response):
self.get_response=get_response
# 服务器第一次启动时候就执行一次之后不再执行的代码
def __call__(self, request,*args, **kwargs):
# 视图函数执行之前的代码
response = self.get_response(request)
# 视图函数执行之后的代码
return response
以上类的方式还可以定义其他中间件,比如:
process_view
,process_exception
,process_template_response
,
下面我们来看具体例子:
1. 在app(非project)中新建任何名字的.py文件,我这里新建的名字为:middleware.py,然后在middleware.py中加入以下代码(需要注意的是中间件的定义有2种方式:函数定义或者类定义):
from django.http import HttpResponse
from django.shortcuts import render
#1.函数方式定义的中间件
# def middleware(get_response):
# #服务器第一次启动的时候执行一次(页仅仅是执行一次而已)
# print('服务器第一次启动的时候执行一次')
# def middleware_body(request):
# print('views之前。。。')
# response=get_response(request)
# print('views之后。。。')
# return response
# return middleware_body
#以下函数不可用,仅仅是测试!从这里可以看出函数式的我定义中间件的方式很有局限性,而且比不怎么模块化!
# def process_view(request,view_func,view_args,view_kwargs):
# print('process_view...')
# return HttpResponse('process_view HttpResponse...')
#2.类方式定义的中间件
class middleware:
def __init__(self,get_response):
self.get_response=get_response
print('服务器第一次启动的时候执行一次')
def __call__(self, request,*args, **kwargs):
print('views之前。。。')
response = self.get_response(request)
print('views之后。。。')
return response
def process_view(self,request,view_func,view_args,view_kwargs):#执行视图函数之前一刻执行
print('process_view...111')
# view_func(request)#在这个函数里面不要执行视图函数,因为这个方法执行完后会
#紧接着执行views.py里面你自己定义的视图函数
# print('process_view...2222')
return None # 在这里可以返回None或者httpresponse对象,
# 但是如果返回httpresponse对象的话则不再执行其他中间件或者是你自己定义的
# views.py里面的视图函数
def process_exception(self,request, exception): #视图函数发生错误后会转来这里执行
print('process_exception')
return HttpResponse(exception) # 在这里可以返回None或者httpresponse对象,
# 但是如果返回httpresponse对象的话则不再执行其他中间件,而是
# 使用默认的方式处理异常。
def process_template_response(self,request, response):
#默认不执行这个函数,除非views函数中返回的实例对象(注意这里这个词)中有render()方法
print('-'*40)
print(response)
print('-' * 40)
print('process_template_response')
#对response实例对象里面的属性进行修改
response.template_name='myuser/index.html'
response.context_data={'age':89,}
return response#必须返回实例对象,返回render()方法会报错!因为
# 在这个方法一旦执行完后会调用这个函数返回的值也就是调用实例对象的render方法。
#下面的函数不起作用,过去遗弃了的方法,在这里测试下而已
# def process_response(request, response):
# print('process_response')
# return HttpResponse('process_response')
# def process_request(request):#匹配url之前执行
# print('process_request')
# return None
2. 接着在setting.py中的MIDDLEWARE加上一行代码来注册上面自定义的中间件:'myuser.middleware.middleware'
(app名.文件名.类名或者函数名---->中间件的定义可用函数或者类),如图:
image.png
3. 在views.py里面的代码如下:
from django.shortcuts import render
from django.http import HttpResponse
from datetime import datetime
from django.utils.timezone import make_aware
def index(request):
response=HttpResponse('index')
expires=datetime(year=2019,month=3,day=30,hour=12,minute=30,second=31)
expires=make_aware(expires)#单是设置了setting中的时区还是不行的,还需要这样转化
response.set_cookie('username','zhiliao',expires=expires)
return response
class Foo():
def __init__(self,req):
self.req=req
self.template_name='myuser/info.html'
self.context_data={'age':16,}
def render(self):
return render(self.req,self.template_name,self.context_data)
#这里才是真正的返回httpresponse给浏览器,在下面的index里面不是真的httpresponse数据
def info(request):
print('info...')
obj = Foo(request)
return obj#这里返回的并不是httpresponse对象,
# 而是一个上面定义的Foo类实例对象
4. 模版templates里面的代码:
index.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>index</h1><br>
age:{{ age }}
</body>
</html>
info.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>info</title>
</head>
<body>
<h1>info</h1><br>
age:{{ age }}
</body>
</html>
网友评论