zoukankan      html  css  js  c++  java
  • 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. 浏览器收到响应结果,对其进行渲染,展示页面
  • 相关阅读:
    BZOJ5212 ZJOI2018历史(LCT)
    BZOJ5127 数据校验
    253. Meeting Rooms II
    311. Sparse Matrix Multiplication
    254. Factor Combinations
    250. Count Univalue Subtrees
    259. 3Sum Smaller
    156. Binary Tree Upside Down
    360. Sort Transformed Array
    348. Design Tic-Tac-Toe
  • 原文地址:https://www.cnblogs.com/liubing8/p/11657238.html
Copyright © 2011-2022 走看看