• Django之视图


    类视图

    1,CBV:类视图

    • 提高了代码的复用性,可以使用面向对象的技术,

    • 可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性

    • Django的url是将一个请求分配给可调用的函数的,而不是一个class。针对这个问题,class-based view提供了一个as_view()静态方法(也就是类方法),调用这个方法,会创建一个类的实例,然后通过实例调用dispatch()方法,dispatch()方法会根据request的method的不同调用相应的方法来处理request(如get() , post()等)。到这里,这些方法和function-based view差不多了,要接收request,得到一个response返回。如果方法没有定义,会抛出HttpResponseNotAllowed异常。

    • dispatch方法

      • 所有支持类似CBV的框架,不限开发语言,都是基于反射来实现的,根据method不同来执行不同的请求方法,CBV的关键就是dispatch方法的使用

      • 在Django里面的base.py中,写好了dispatch()来处理请求

      • url访问的时候,会执行as_view()方法

      • urlpatterns = [
            url(r'^admin/', admin.site.urls),
            url(r'^index/', views.IndexView.as_view())     # 执行类后面的as_view()方法,是父类里面的方法
        ]
        
      • 然后as_view在base.py中的view类里面

    • 这里能看出执行as_view()时返回view会执行view方法,view方法又会调用dispatch方法,返回dispatch方法的返回值

    • self = cls(**initkwargs)
      
    • 这里的cls就是请求的类,把这个indexView实例化了

    • 这里就是一个修饰器功能
      我们可以通过重写dispatch方法来自定义处理请求:
      在我们的写的IndexView类里面,重写dispatch()

      class IndexView(View):
          def dispatch(self, request, *args, **kwargs):
              return HttpResponse("dispatch")
          
          def get(self,request,*args,**kwargs):
              return HttpResponse("GET")
          def post(self,request,*args,**kwargs):
              return HttpResponse("POST")
          def put(self,request,*args,**kwargs):
              return HttpResponse("PUT")
          def delete(self,request,*args,**kwargs):
              return HttpResponse("DELET")
      

      根据上面写的代码,因为无论请求是什么都会执行dispatch方法,所以无论请求是什么都会返回“dispatch”,那么我们就可以在自己写的这个dispatch方法中自定义,根据请求类型执行什么操作。

      class IndexView(View):
          def dispatch(self, request, *args, **kwargs):
              #
              func = getattr(self,request.method.lower)
              ret = func(request, *args, **kwargs)
              return ret
      
          def get(self,request,*args,**kwargs):
              return HttpResponse("GET")
          def post(self,request,*args,**kwargs):
              return HttpResponse("POST")
          def put(self,request,*args,**kwargs):
              return HttpResponse("PUT")
          def delete(self,request,*args,**kwargs):
              return HttpResponse("DELET")
      

      这样就可以根据请求类型,用getattr判断,这里注意返回的request.method是大写的,需要小写。
      当然这个dispatch在父类View写好了,不用我们写,这里用于理解源码中的dispatch方法

    • 代码示例

    • views.py文件

    from django.shortcuts import render,HttpResponse
    
    # Create your views here.
    from django.views import View
    
    
    class LoginView(View):
        """
        CBV:class base views,就是视图里使用类处理请求,面向对象的编程
        """
    
        def dispatch(self, request, *args, **kwargs):
            print("请求来了")
            ret = super(LoginView, self).dispatch(request, *args, **kwargs)
            print("请求结束")
            return ret
    
        def get(self,request):
            print("这是get请求")
            return render(request, "login.html")
    
        def post(self):
            return HttpResponse("登录成功")
    
    • urls.py文件
    from wednesday.views import LoginView
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^login/', LoginView.as_view()),
    ]
    
    
    #######urls.py路由写法
    url(r'^login/', views.LoginView.as_view()),
    

    2,FBV:function base views

    • 在我们日常学习Django中,都是用的FBV(function base views)方式,就是在视图中用函数处理各种请求。而CBV(class base view)则是通过类来处理请求。
      Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承、封装、多态)。所以Django在后来加入了Class-Based-View。可以让我们用类写View。这样做的优点主要下面两种:

      • 提高了代码的复用性,可以使用面向对象的技术,比如Mixin(多继承)
      • 可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性
    • 两者区别

      • FBV:FBV就是在url中一个路径对应一个函数

        • 在url中

          fbv就是在url中一个路径对应一个函数
          urlpatterns = [
              url(r'^admin/', admin.site.urls),
              url(r'^index/', views.index)
          

        ]

        
        - 在视图函数中
        
        

        def index(request):
        return render(request, 'index.html')

        
        
        
        
      • CBV就是在url中一个路径对应一个类

        • 在url中

          urlpatterns = [
              url(r'^admin/', admin.site.urls),
              url(r'^index/', views.IndexView.as_view())     # 执行类后面的as_view()方法,是父类里面的方法
          

      ]
      ```

      • 在视图函数中

        from django.views import View
        class IndexView(View):
          
            # 以get形式访问会执行get函数,一般情况下获取数据
            def get(self, *args, **kwargs):  
                return HttpResponse('666')
              
            # 以post形式访问的话会执行post函数,一般情况下发送数据
            def post(self, *args, **kwargs):  
                return HttpResponse('999')
        
    • 特别注意

      • CBV定义类的时候必须继承view
      • 在写url的时候必须加as_view
      • 类里面使用form表单提交的话只有get和post方法

    3,视图装饰器

    • 添加装饰器前必须导入from django.utils.decorators import method_decorator

    • 添加装饰器的格式必须为@method_decorator(),括号里面为装饰器的函数名

    • 给类添加是必须声明name

    • 注意csrf-token装饰器的特殊性,在CBV模式下它只能加在dispatch上面(后面再说)

      下面这是csrf_token的装饰器:
      
        @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置csrfToken全局中间件。
      
        @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
      
        注意:from django.views.decorators.csrf import csrf_exempt,csrf_protect
        
      
    • 类装饰器的三种方式

      • 单一装饰

        from django.utils.decorators import method_decorator
        from django.views import View
        
        
        def wrapper(func):
            def inner(*args, **kwargs):
                print("被装饰前")
                ret = func(*args, **kwargs)
                print("被装饰后")
                return ret
            return inner
            
            
        class LoginView(View):
            """
            CBV:class base views,就是视图里使用类处理请求,面向对象的编程
            使用装饰器装饰CBV,Django中提供了method_decorator装饰器
            用于将装饰器转换为方法装饰器
        
            """
            #第一种方式
            @method_decorator(wrapper)
            def get(self, request):
                print("这是get请求")
                return render(request, "login.html")
        
            def post(self, request):
                print(request.POST)
                return HttpResponse("登录成功")
        
      • 多个函数装饰

        from django.utils.decorators import method_decorator
        from django.views import View
        
        
        def wrapper(func):
            def inner(*args, **kwargs):
                print("被装饰前")
                ret = func(*args, **kwargs)
                print("被装饰后")
                return ret
            return inner
            
        class LoginView(View):
            """
            CBV:class base views,就是视图里使用类处理请求,面向对象的编程
            使用装饰器装饰CBV,Django中提供了method_decorator装饰器
            用于将装饰器转换为方法装饰器
        
            """
            #第二种方式,批量对具体的请求处理方法,get,post都会执行装饰器函数
            @method_decorator(wrapper)
            def dispatch(self, request, *args, **kwargs):
                print("请求来了")
                ret = super(LoginView, self).dispatch(request, *args, **kwargs)
                print("请求结束")
                return ret
        
            def get(self, request):
                print("这是get请求")
                return render(request, "login.html")
        
            def post(self, request):
                print(request.POST)
                return HttpResponse("登录成功")
        
    希望你眼眸有星辰,心中有山海,从此以梦为马,不负韶华
  • 相关阅读:
    [推荐]大量 Blazor 学习资源(二)
    [翻译]欢迎使用C#9.0
    重磅消息:微软发布多平台应用UI框架 MAUI,网友直呼:牛x
    如何对Git的分支进行管理
    如何使用JPA的@Formula注解
    伤其十指,不如断其一指,谈谈我的学习计划
    如何使用Swagger-UI在线生成漂亮的接口文档
    如何在Linux服务器上部署jar包
    使用PageHelper插件分页时,如何对对象进行转换以及添加属性
    在Java中使用Collections.sort 依据多个字段排序
  • 原文地址:https://www.cnblogs.com/daviddd/p/12049894.html
Copyright © 2020-2023  润新知