首页 > 其他分享 >Django框架之中间件引入

Django框架之中间件引入

时间:2024-03-25 18:12:54浏览次数:32  
标签:框架 process 中间件 request Django print response view

【一】中间件介绍

  • 之前我们通过给视图函数加上装饰器来判断用户是否登录,把没有登陆的用户请求跳转到登录页面。
  • 但是如果有很多的功能都需要在登录之后才能使用,那么每个功能对应的视图函数都需要加上装饰器,这样的话就略显繁琐
  • 通过django中间件就可以实现控制全局的效果

【1】什么是中间件

  • 官方的说法是,中间件是一个用于处理DJango的请求和响应的框架级别的钩子。他是一个轻量,低级别的插件系统,用于在全局范围内改变django的输入和输出。每个中间件组件都负责做一些特别的功能
  • 由于它的作用是对全局的影响,所以需要谨慎使用,要不然会影响性能。
  • 简单来说,中间件可以定义我们的视图函数在执行之前和执行之后的一些操作,他的本质上是一个自定义类,类中定义了几个方法,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',
]

【二】自定义中间件

  • 最好现在应用下创建一个文件夹,文件夹下创建py文件,py文件内导入MiddlewareMixin
  • 写一个类继承MiddlewareMixin
  • django给了我们五个可以自定义的中间件方法
# 可以自定义的方法
# 1.在视图函数接收到请求之前触发
process_request(self,request)

# 2.视图函数被掉哟ing之前触发
process_view(self, request, view_func, view_args, view_kwargs)

# 3.这个方法会在 Django 框架中的视图函数返回一个 TemplateResponse 对象后执行。
process_template_response(self,request,response)

# 4.发生异常后执行
process_exception(self, request, exception)

# 5.响应数据时执行
process_response(self, request, response)

# 必须要掌握的
1.process_request(self,request)
2.process_response(self, request, response)

# 以上的方法返回值可以是None,或者是一个HttpResponse对象,如果是None,就按照原本的规则运行,
# 果如返回了HttpResponse对象,那么直接返回一个页面

【1】process_request

  • process_request有一个参数就是request,这个request和视图函数里面的request对象是一样的,在中间件中,在请求达到url之前,可以对这个对象做一系列操作
  • 它的返回值可以是一个None,或者是一个HttpResponse对象,如果是None,就正常走到后面的路由视图等,如果是HttpResponse对象,那么直接将这个对象返回到浏览器渲染
  • 一下是一些对中间件的研究

多个中间件,Django是如何执行其中的process_request方法的

# 多个中间件,Django是如何执行其中的process_request方法的

# 自定义中间件
class MyMid(MiddlewareMixin):
    def process_request(self, request):
        print('我是来自第一个中间件的request的消息')


class MyMid2(MiddlewareMixin):
    def process_request(self, request):
        print('我是来自第二个中间件的request的消息')
       
# 中间件配置
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',
    'app1.mymiddleware.mymid.MyMid',
    'app1.mymiddleware.mymid.MyMid2'
]

# 视图函数
def index(request):
    print('这是视图函数的index')
    return HttpResponse('index')

# 访问index控制台输出结果
我是来自第一个中间件的request的消息
我是来自第二个中间件的request的消息
这是视图函数的index

# 结论
1.中间件的process_request方法是在执行视图函数之前执行的
2.django在执行中间件的process_request方法是按照配置文件从上到下的顺序来的
3.不同中间件之间传递的request是同一个对象

【2】process_response

  • 定义process_response方法时,必须要传入两个形参,request和response。
  • 这个方法必须要返回response或者HttpResponse对象
  • response对象就是django视图函数返回的对象
# 多个中间件,Django是如何执行其中的process_response方法的

# 自定义中间件
class MyMid(MiddlewareMixin):
    def process_request(self, request):
        print('我是来自第一个中间件的request的消息')

    def process_response(self, request, response):
        print('我是来自第一个中间件的响应消息')
        return response


class MyMid2(MiddlewareMixin):
    def process_request(self, request):
        print('我是来自第二个中间件的request的消息')

    def process_response(self, request, response):
        print('我是来自第二个中间件的响应消息')
        return response

# 中间件配置
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',
    'app1.mymiddleware.mymid.MyMid',
    'app1.mymiddleware.mymid.MyMid2'
]

# 视图函数
def index(request):
    print('这是视图函数的index')
    return HttpResponse('index')

# 访问index控制台输出结果
我是来自第一个中间件的request的消息
我是来自第二个中间件的request的消息
这是视图函数的index
我是来自第二个中间件的响应消息
我是来自第一个中间件的响应消息

# 总结
1.这里返回的resonse对象就是视图函数返回的HttpResponse对象
2.执行的顺序是按照配置列表从下到上执行的
3.不同中间件之间传递的response是同一个对象

【3】processs_view

  • 该方法有四个参数process_view(self, request, view_func, view_args, view_kwargs)
  • request就是和视图函数的request对象是一样的,
  • view_func是Django即将使用的视图函数
  • view_args是将要传递给视图函数的位置参数列表
  • view_kwargs是将要传递给视图函数的关键字参数字典
  • Django在调用视图函数之前回调用process_view方法
  • 它应该返回一个None或者一个HttpResponse对象,如果返回None,将继续执行其他中间件的processs_view方法,如果返回HttpResponse对象,Django将不在执行其他的业务逻辑,会直接掉头从配置列表中最后一个中间件的process_response开始依次执行
# 自定义中间件
class MyMid(MiddlewareMixin):
    def process_request(self, request):
        print('我是来自第一个中间件的request的消息')

    def process_response(self, request, response):
        print('我是来自第一个中间件的响应消息')
        return response
    def process_view(self, request, view_func, view_args, view_kwargs):
        print('------------------------------------------')
        print('我是来自第一个中间件的process_view')
        print(view_func, view_func.__name__)


class MyMid2(MiddlewareMixin):
    def process_request(self, request):
        print('我是来自第二个中间件的request的消息')

    def process_response(self, request, response):
        print('我是来自第二个中间件的响应消息')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print('------------------------------------------')
        print('我是来自第二个中间件的process_view')
        print(view_func, view_func.__name__)
        
# 控制台输出
我是来自第一个中间件的request的消息
我是来自第二个中间件的request的消息
------------------------------------------
我是来自第一个中间件的process_view
<function index at 0x0000027D5FCA71A0> index
------------------------------------------
我是来自第二个中间件的process_view
<function index at 0x0000027D5FCA71A0> index
这是视图函数的index
我是来自第二个中间件的响应消息
我是来自第一个中间件的响应消息

        
# 总结
1.process_view方法会在执行process_request方法之后,视图函数之前运行
2.多个中间件的process_view是按照配置文件列表顺序来执行的

【4】process_exception

  • 该方法有两个参数,process_exception(self, request, exception)
  • 一个是request对象
  • 另一个exception是视图函数发生异常而产生的Exception对象
  • 这个方法只有在视图函数发生异常了还会执行,他的返回值可以是一个None也可以是一个HttpResponse对象
  • 如果是HttpResponse对象,Django将调用模板和中间件中的process_response方法,并且返回给浏览器。
  • 如果返回的是None,那么将默认处理异常
# 自定义中间件
class MyMid(MiddlewareMixin):
    def process_request(self, request):
        print('我是来自第一个中间件的request的消息')

    def process_response(self, request, response):
        print('我是来自第一个中间件的响应消息')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print('------------------------------------------')
        print('我是来自第一个中间件的process_view')
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(f'中间件1的错误消息:>>>>>>{exception}')


class MyMid2(MiddlewareMixin):
    def process_request(self, request):
        print('我是来自第二个中间件的request的消息')

    def process_response(self, request, response):
        print('我是来自第二个中间件的响应消息')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print('------------------------------------------')
        print('我是来自第二个中间件的process_view')
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(f'中间件2的错误消息:>>>>>>{exception}')
        
# 视图函数手动制造错误
def index(request):
    print('这是视图函数的index')
    asdasdasd
    return HttpResponse('index')

# 访问index控制台输出消息
我是来自第一个中间件的request的消息
我是来自第二个中间件的request的消息
------------------------------------------
我是来自第一个中间件的process_view
<function index at 0x000001CACF6F7100> index
------------------------------------------
我是来自第二个中间件的process_view
<function index at 0x000001CACF6F7100> index
这是视图函数的index
中间件2的错误消息:>>>>>>name 'asdasdasd' is not defined
中间件1的错误消息:>>>>>>name 'asdasdasd' is not defined
我是来自第二个中间件的响应消息
我是来自第一个中间件的响应消息

# 总结
1.process_exception方法只有在视图函数抛出异常后才会被调用
2.在抛出异常的前提下,它是在执行完视图函数之后被调用的
3.多个中间件的process_exception方法是配置列表逆序执行的

【5】process_template_response

  • 这个方法用的比较少,它有两个参数process_template_response(self, request, response)
  • 一个是request对象,另一个是TemplateResponse对象,由视图函数后者中间件产生
  • process_template_response实在视图函数执行完成之后立刻执行,但是他有一个条件,那就是视图函数返回的对象有一个render()方法
# 自定义中间件
class MyMid(MiddlewareMixin):
    def process_request(self, request):
        print('我是来自第一个中间件的request的消息')

    def process_response(self, request, response):
        print('我是来自第一个中间件的响应消息')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print('------------------------------------------')
        print('我是来自第一个中间件的process_view')
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(f'中间件1的错误消息:>>>>>>{exception}')

    def process_template_response(self, request, response):
        print("MD1 中的process_template_response")
        return response


class MyMid2(MiddlewareMixin):
    def process_request(self, request):
        print('我是来自第二个中间件的request的消息')

    def process_response(self, request, response):
        print('我是来自第二个中间件的响应消息')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print('------------------------------------------')
        print('我是来自第二个中间件的process_view')
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(f'中间件2的错误消息:>>>>>>{exception}')

    def process_template_response(self, request, response):
        print("MD2 中的process_template_response")
        return response
    
# 视图函数
def index(request):
    def render():
        print('我是视图函数的render')
        return HttpResponse('无敌了孩子')

    print('这是视图函数的index')
    rep = HttpResponse('index')
    rep.render = render
    return rep

# 控制台输出
我是来自第一个中间件的request的消息
我是来自第二个中间件的request的消息
------------------------------------------
我是来自第一个中间件的process_view
<function index at 0x0000020E5BE967A0> index
------------------------------------------
我是来自第二个中间件的process_view
<function index at 0x0000020E5BE967A0> index
这是视图函数的index
MD2 中的process_template_response
MD1 中的process_template_response
我是视图函数的render
我是来自第二个中间件的响应消息
我是来自第一个中间件的响应消息



【三】中间件执行流程

  • 请求到达中间件之后,先按照顺序执行每个中间件的process_request方法
  • process_request方法返回值是None就以此执行,如果返回值是HttpResponse对象,那么不在执行后面的process_request方法,而是将这个HttpResponse对象带到当前这个中间件对应的process_response方法,在按照配置列表的逆序执行

img

  • process_request对象都执行完了之后,会进行匹配路由,匹配到路由之后会执行列表第一个中间件的process_view方法,如果所有的中间件的process_view方法返回的都是None,那么将执行对应的视图函数,如果有一个中间件返回了HttpResponse对象,那么将不执行视图函数,之间从列表的最后一个中间件的process_response对象开始执行

img

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

img

img

标签:框架,process,中间件,request,Django,print,response,view
From: https://www.cnblogs.com/Hqqqq/p/18095007

相关文章

  • Django框架之Cookie和Session
    【一】Cookie与Session介绍【1】早期的网站早期的很多网站可能都没有保存用户功能的需求,所有用户访问的返回结果都是一样的,如新闻,博客文章等等...但是互联网发展至今,已经有绝大多数网站,在你登录后反馈的页面和不登录反馈的页面已经是不一样的了,这些网站就用到了保存用户登录信......
  • Django框架之csrf跨站请求
    【一】跨站请求伪造介绍【1】引入CSRF(Cross-SiteRequestForgery)跨站请求伪造是一种常见的网络攻击方式。攻击者通过诱导受害者访问恶意网站或点击恶意链接将恶意请求发送到目标网站上利用受害者在目标网站中已登录的身份来执行某些操作从而达到攻击的目的。【2】举......
  • Django框架之中间件思想
    【一】引入我们在Django的配置文件中,里面的中间件配置文件虽然使用逗号分开,但是可以直接映入到某个模块MIDDLEWARE=['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.C......
  • Django框架之auth模块
    【一】Auth模块引入auth模块是django自带的用户认证模块当我们开发一个网站的时候,无可避免的需要设计实现网站的用户登陆系统。此时我们需要实现包括用户的注册,登录,全局登录认证,注销,修改密码等等,如果要靠自己一点点敲代码完成,那实在是太繁琐了Django为我们提供的Auth模块......
  • express中间件
    听的不是很懂,不知道具体有多大的作用。绑定到app实例上的中间件,都可以叫做  应用级中间件;错误级别中间件: 这有一点需要注意,就是错误级别中间件要放在路由的后面,和其他中间件不一样,他们都必须要写在路由前面。 express内置的中间件:这一部分也是听的好没意思,用gpt生成......
  • Django框架静态文件
    【一】静态文件配置说明【1】模板文件通常html文件都会放在templates文件夹下【2】资源文件资源文件也就是jQuery,bootstrap这些前端框架这些都统称为静态文件,通常默认是放在static文件夹里面的static内部又通常分为以下三部分cssjssimgplugins【二】静态文件配......
  • Django框架之ORM操作
    【一】配置数据库【1】默认数据库在settings.py文件中的DATABASES字典就是用来配置数据库的默认的数据库是django自带的数据库是sqlite3DATABASES={'default':{'ENGINE':'django.db.backends.sqlite3','NAME':BASE_DIR/'db.sqlite3',......
  • Django框架之requests对象
    【一】requests对象引入【1】提交GET请求前端form表单中action属性,如果不写的话,默认就是向当前路由请求form表单中的method属性,如果不写默认就是GET请求<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title>{%lo......
  • Django框架之视图层
    【一】视图层三板斧HttpResponse非常重要,因为三板斧的三个方法返回的都是HttpResponse对象通过看源码可以发现各种各样的类,最终都是由HttpResponse这个类继承而来的【1】HttpResponseHttpResponse是Django中用于创建HTTP响应的一个类,它可以方便的把一些自定义的文本内容或......
  • Django框架之路由层
    【一】Django的路由系统【1】什么是URL配置URL调度器|Django文档|Django(djangoproject.com)URL配置的本质就是让URL与视图函数之间有对应的关系当在浏览器输入对应的URL,django就能通过URL配置去找对应的视图函数【2】基本格式##Django1.x版本语法fromdjango.co......