• Django框架10 /sweetalert插件、django事务和锁、中间件、django请求生命周期


    Django框架10 /sweetalert插件、django事务和锁、中间件、django请求生命周期

    1. SweetAlert插件示例

    • 使用流程:

      1. 在github下载css、js文件放到项目静态文件夹中,https://github.com/LBZHK/bootstrap-sweetalert
      2. 在html页面分别引入jquery、bootstrap文件,sweetalert是基于bootstrap实现,bootstrap是基于jquery实现的
      3. 将代码复制到script标签中
    • 代码示例:

      $(".btn-danger").on("click", function () {
        swal({
          title: "你确定要删除吗?",
          text: "删除可就找不回来了哦!",
          type: "warning",
          showCancelButton: true,
          confirmButtonClass: "btn-danger",
          confirmButtonText: "删除",
          cancelButtonText: "取消",
          closeOnConfirm: false
          },
          function () {
            var deleteId = $(this).parent().parent().attr("data_id");
            // 注意:此处$(this)已经不是".btn-danger"这个点击的对象
            $.ajax({
              url: "/delete_book/",
              type: "post",
              data: {"id": deleteId},
              success: function (data) {
                if (data.status === 1) {
                  swal("删除成功!", "你可以准备跑路了!", "success");
                } else {
                  swal("删除失败", "你可以再尝试一下!", "error")
                }
              }
            })
          });
      })
      

      img

    2. django事务和锁

    • mysql

      # 锁:
      select * from book where id=1 for update;
      
      # 事务:
      begin/start trancsation   # 开启事务
      	select * from book where id=1 for update;
      commit   # 提交
      rollback   # 回滚
      
    • django orm的事务/锁

      models.Book.objects.select_for_update().filter(id=1)
      

      事务

      • 全局开启事务
      # 1.在Web应用中,常用的事务处理方式是将每个请求都包裹在一个事务中。这个功能使用起来非常简单,你只需要将它的配置项ATOMIC_REQUESTS设置为True。
      
      # 2.当有请求过来时,Django会在调用视图方法前开启一个事务。如果请求正确处理并正确返回了结果,Django就会提交该事务。否则,Django会自动回滚该事务。
      
      DATABASES = {
          'default': {
              'ENGINE': 'django.db.backends.mysql',
              'NAME': 'mxshop',
              'HOST': '127.0.0.1',
              'PORT': '3306',
              'USER': 'root',
              'PASSWORD': '123',
              'OPTIONS': {
                  "init_command": "SET default_storage_engine='INNODB'",
             #'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", # 配置开启严格sql模式
      
              }
              "ATOMIC_REQUESTS": True,  # 全局开启事务,绑定的是http请求响应整个过程
              "AUTOCOMMIT":False,   # 全局取消自动提交,慎用
          },
        'other':{
          'ENGINE': 'django.db.backends.mysql', 
                  ......
        }   # 还可以配置其他数据库
      }
      
      • 局部使用事务

      用法1:给函数做装饰器来使用

      from django.db import transaction
      
      @transaction.atomic
      def viewfunc(request):
          # This code executes inside a transaction.
          do_stuff()
      

      用法2:作为上下文管理来使用,其实就是设置事务的保存点

      from django.db import transaction
      
      def viewfunc(request):
          # This code executes in autocommit mode (Django's default).
          do_stuff()
      
          with transaction.atomic():   # 保存点
              # This code executes inside a transaction.
              do_more_stuff()
      
          do_other_stuff()
      

    3. 中间件

    • 中间件概述

      中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变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',
      ]
      
      # MIDDLEWARE配置项是一个列表,列表中是一个个字符串,这些字符串其实是一个个类,也就是一个个中间件。
      
    • 自定义中间件

      # 中间件可以定义五个方法,分别是:
      
      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)
      
      # 主要的是process_request和process_response
      # 以上方法的返回值可以是None或一个HttpResponse对象,如果是None,则继续按照django定义的规则向后继续执行,如果是HttpResponse对象,则直接将该对象返回给用户。
      
      # 注意:将自定义中间件添加到setting文件中MIDDLEWARE注意顺序
      
    • process_request

      def process_request(self, request):
          print("MD1里面的 process_request")
          
      # 1.process_request有一个参数,就是request,这个request和视图函数中的request是一样的
      # 2.process_request方法里面不写返回值,默认也是返回None,如果写了return None,也是一样的效果,不会中断请求,但是如果return 的一个httpresponse对象,那么就会在这个方法中断请求,直接返回给用户,这就成了非正常的流程了
      # 3.如果在这里return了httpresponse对象,那么会从这个中间件类中的process_response方法开始执行返回操作,所以这个类里面只要有process_response方法,肯定会执行
      

      示例代码:

      # settings.py的MIDDLEWARE配置项
      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',
          'middlewares.MD1',  # 自定义中间件MD1,这个写的是项目路径下的一个路径,
          # 例如,如果放在项目下,文件夹名成为utils,那么这里应该写utils.middlewares.MD1
          'middlewares.MD2'  # 自定义中间件MD2
      ]
      
      from django.utils.deprecation import MiddlewareMixin
      class MD1(MiddlewareMixin):
          def process_request(self, request):
              print("MD1里面的 process_request")
      
      class MD2(MiddlewareMixin):
          def process_request(self, request):
              print("MD2里面的 process_request")
              pass
          
      # 结果:
      MD1里面的 process_request
      MD2里面的 process_request
      app01 中的 index视图
      
    • process_response

      def process_response(self,request,response):
          return response
          
      # 1.它有两个参数,一个是request,一个是response,request就是上述例子中一样的对象,response是视图函数返回的HttpResponse对象。该方法的返回值也必须是HttpResponse对象
      # 2.注意:process_response函数要有return response返回值
      

      示例代码:

      from django.utils.deprecation import MiddlewareMixin
      from django.shortcuts import HttpResponse
      
      class Md1(MiddlewareMixin):
          def process_request(self,request):
              print("Md1请求")
       
          def process_response(self,request,response):
              print("Md1返回")
              return response
      
      class Md2(MiddlewareMixin):
          def process_request(self,request):
              print("Md2请求")
              # return HttpResponse("Md2中断")
          def process_response(self,request,response):
              print("Md2返回")
              return response  ****
          
      # 结果:
      Md1请求
      Md2请求
      view函数...
      Md2返回
      Md1返回
      
    • process_view

      process_view(self, request, view_func, view_args, view_kwargs)
      
      # Django会在执行完url控制器后,调用视图函数之前调用process_view方法
      
      # 四个参数:
      # request是HttpRequest对象。
      # view_func是Django即将使用的视图函数/它是实际的函数对象,而不是函数的名称作为字符串。
      # view_args是将传递给视图的位置参数的列表.
      # view_kwargs是将传递给视图的关键字参数的字典/view_args和view_kwargs都不包含第一个视图参数(request)。
      
      # 可以返回None或一个HttpResponse对象。 
      # 如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。 
      # 如果它返回一个HttpResponse对象,Django不会调用对应的视图函数。 它将执行中间件的process_response方法并将应用到该HttpResponse并返回结果。
      

      示例代码:

      from django.utils.deprecation import MiddlewareMixin
      
      
      class MD1(MiddlewareMixin):
          def process_request(self, request):
              print("MD1里面的 process_request")
          def process_response(self, request, response):
              print("MD1里面的 process_response")
              return response
          def process_view(self, request, view_func, view_args, view_kwargs):
              print("-" * 80)
              print("MD1 中的process_view")
              print(view_func, view_func.__name__) 
              # 就是url映射到的那个视图函数,也就是说每个中间件的这个process_view已经提前拿到了要执行的那个视图函数
              # ret = view_func(request)  # 提前执行视图函数,不用到了上图的视图函数的位置再执行,如果视图函数有参数的话,可以这么写 view_func(request,view_args,view_kwargs) 
              # return ret  # 直接就在MD1中间件这里这个类的process_response给返回了,就不会去找到视图函数里面的这个函数去执行了。
      
      class MD2(MiddlewareMixin):
          def process_request(self, request):
              print("MD2里面的 process_request")
              pass
      
          def process_response(self, request, response):
              print("MD2里面的 process_response")
              return response
      
          def process_view(self, request, view_func, view_args, view_kwargs):
              print("-" * 80)
              print("MD2 中的process_view")
              print(view_func, view_func.__name__)
              
       # 结果:
      MD2里面的 process_request
      MD1里面的 process_request
      -------------------------------------------------------------------------------
      MD2 中的process_view
      <function index at 0x000001DE68317488> index
      -------------------------------------------------------------------------------
      MD1 中的process_view
      <function index at 0x000001DE68317488> index
      app01 中的 index视图
      MD1里面的 process_response
      MD2里面的 process_response
      

      正常流程图:

      非正常流程图:

    • process_exception

      process_exception(self, request, exception)
      
      # 两个参数:
      # 1.一个HttpRequest对象
      # 2.一个exception是视图函数异常产生的Exception对象。
      
      # 这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个None也可以是一个HttpResponse对象。
      # 如果是HttpResponse对象,Django将调用模板和中间件中的process_response方法,并返回给浏览器,否则将默认处理异常。
      # 如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行。
      

      代码示例:

      def index(request):
          print("app01 中的 index视图")
          raise ValueError("呵呵")
          return HttpResponse("O98K")
      
      from django.utils.deprecation import MiddlewareMixin
      
      
      class MD1(MiddlewareMixin):
      
          def process_request(self, request):
              print("MD1里面的 process_request")
      
          def process_response(self, request, response):
              print("MD1里面的 process_response")
              return response
      
          def process_view(self, request, view_func, view_args, view_kwargs):
              print("-" * 80)
              print("MD1 中的process_view")
              print(view_func, view_func.__name__)
      
          def process_exception(self, request, exception):
              print(exception)
              print("MD1 中的process_exception")
      
      
      class MD2(MiddlewareMixin):
          def process_request(self, request):
              print("MD2里面的 process_request")
              pass
      
          def process_response(self, request, response):
              print("MD2里面的 process_response")
              return response
      
          def process_view(self, request, view_func, view_args, view_kwargs):
              print("-" * 80)
              print("MD2 中的process_view")
              print(view_func, view_func.__name__)
      
          def process_exception(self, request, exception):
              print(exception)
              print("MD2 中的process_exception")
              
             
      # 结果:
      MD1里面的 process_request
      MD2里面的 process_request
      --------------------------------------------------------------------------------
      MD1 中的process_view
      <function index at 0x0000022C09727488> index
      --------------------------------------------------------------------------------
      MD2 中的process_view
      <function index at 0x0000022C09727488> index
      app01 中的 index视图
      呵呵
      MD2 中的process_exception
      MD2里面的 process_response
      MD1里面的 process_response
      
      
      # 注意,这里并没有执行MD2的process_exception方法,因为MD1中的process_exception方法直接返回了一个响应对象。
      

      正常流程图:

      非正常流程图:

    • process_template_response

      process_template_response(self, request, response)
      
      # 参数:
      # 1.request是HttpRequest对象
      # 2.response是TemplateResponse对象(由视图函数或者中间件产生)。
      
      # process_template_response是在视图函数执行完成后立即执行,但是它有一个前提条件,那就是视图函数返回的对象有一个render()方法(或者表明该对象是一个TemplateResponse对象或等价方法)。
      

      代码示例:

      def index(request):
          print("app01 中的 index视图")
        #raise ValueError('出错啦') 
          def render():
              print("in index/render")  
              # raise ValueError('出错啦') # 至于render函数中报错了,那么会先执行process_template_response方法,然后执行process_exception方法,如果是在render方法外面报错了,那么就不会执行这个process_template_response方法了。
              return HttpResponse("O98K") # 返回的将是这个新的对象
          	# raise ValueError('出错啦') 将报错放到这个位置不会报错
          rep = HttpResponse("OK")
          rep.render = render
          return rep
      
    • cookie认证/中间件版

      class M1(MiddlewareMixin):
          def process_request(self,request):
              # 设置路径白名单,只要访问的是login登陆路径,就不做这个cookie认证
              if request.path not in [reverse('login'),]:
                  print('我是M1中间件') 
                  is_login = request.COOKIES.get('is_login', False)
                  if is_login:
                      pass
                  else:
                      # return render(request,'login.html')
                      return redirect(reverse('login'))
              else:
                  return None  # 别忘了return None,或者直接写个pass
      
          def process_response(self,request,response):
              print('M1响应部分')
              return response
      

    4. 中间件应用/登录认证

    • view

      from django.shortcuts import render,HttpResponse,redirect
      
      def login(request):
          if request.method == 'GET':
              return render(request,'login.html')
          else:
              name = request.POST.get('name')
              password = request.POST.get('password')
              if name == 'liu' and password == '123':
                  request.session['is_login'] = True
                  return redirect('index')
              else:
                  return redirect('login')
      
      def index(request):
          return render(request,'index.html')
      
    • mymiddleware.py

      from django.utils.deprecation import MiddlewareMixin
      from django.shortcuts import HttpResponse,render,redirect
      
      class MD1(MiddlewareMixin):
          white_list = ['/login/']
          def process_request(self,request):
              print('请求来了')
              path = request.path
              if  path not in self.white_list:
                  status = request.session.get('is_login')
                  if not status:
                      return redirect('login')
      
          def process_response(self,request,response):
              print('响应走了')
              return response
      
    • login.html

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body>
      <h1>登录页面</h1>
      <form action="" method="post">
          {% csrf_token %}
      用户名:<input type="text" name="name">     <!--input标签记得写name-->
      密码:<input type="text" name="password">
      <button class="submit">提交</button>
      </form>
      </body>
      <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
      <script></script>
      </html>
      

    5. django请求生命周期

    • 流程描述:
      1. 在浏览器输入网址后,先经过DNS域名解析,解析出对应的ip
      2. 请求到达wsgi,在wsgi封装了socket,按着http协议解包,将请求封装成request对象
      3. 到达中间件,按顺序执行每个中间件的request方法
      4. 在url控制器中,映射到对应的视图函数
      5. 在视图函数中,进行数据库相关操作,以及模板渲染
      6. 将视图返回结果,返回到中间件,按倒序执行每个中间件的response方法
      7. 将返回结果通过wsgi,按照http协议封装响应数据,返回给浏览器
      8. 浏览器收到响应结果,对其进行渲染,展示页面
  • 相关阅读:
    每次运行caffe代码之前需要考虑修改的地方
    caffe solver 配置详解
    python获取当前文件路径以及父文件路径
    Python 文件夹及文件操作
    安装NVIDIA驱动时禁用自带nouveau驱动
    博客园转载其他博客园的文章:图片和源码
    分布式开放消息系统(RocketMQ)的原理与实践
    RocketMQ基本概念及原理介绍
    rocketmq 4.3.2 解决远程不能消费问题,解决未识别到公网IP问题
    osx免驱网卡推荐
  • 原文地址:https://www.cnblogs.com/liubing8/p/11657238.html
Copyright © 2020-2023  润新知