zoukankan      html  css  js  c++  java
  • 第5天:基于类的视图与中间件

    •  类视图引入
    •  类视图的定义与使用
    •  类视图实现的原理
    •  在类视图中使用装饰器
    •  类视图多继承&Minx扩展类
    •  中间件

    类视图引入

    以函数的方式定义的视图成为函数视图,函数视图便于理解。但是遇到一个视图对应的路径提供了多种不同HTTP请求方式的支持时,就需要在一个函数中编写不同的业务逻辑,代码可读性与复用性都不佳

    def register(request):
        """处理注册"""
    
        #获取请求方法,判断是GET/POST请求
        if request.method == 'GET':
            #处理GET请求,返回注册页面
            return render(request, 'register.html')
        else:
            #处理POST请求,实现注册逻辑
            return HttpResponse('这里实现注册逻辑')
    函数视图示例

    在Django中也可以使用类来定义一个视图,称为类视图

    def register(View):
        """类视图 处理注册"""
        
        def get(self, request):
            "处理GET请求, 返回注册页面"
            return render(request, 'register.html')
        
        def post(self, request):
            " 处理POST请求,实现注册逻辑"
            return HttpResponse('这里实现注册逻辑')
    类视图示例

    类视图好处:

    • 代码可读性好
    • 类视图相对于函数视图通过继承具有更高的可复用性

    类视图的定义与使用

    我们要想使用类视图必须继承View

    from django.views.generic import View

    from django.views.generic import View
    
    
    class DemoView(View):
        def get(self, request):
            return HttpResponse('get page')
        
        def post(self, request):
            return HttpResponse('post page')
    DemoView

    路由那里,我则需要使用该视图的as_view方法转换为函数

    from .views import DemoView
    
    urlpatterns = [
        url(r'^demo/$', DemoView.as_view(), name='demo')
    ]
    路由配置

    类视图实现的原理

     按住ctrl,点击as_view

    @classonlymethod
    def as_view(cls, **initkwargs):
        """
        Main entry point for a request-response process.
        """
        ...
    
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)     #cls就是DemoView类,生成对象
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs
    
        update_wrapper(view, cls, updated=())
    
        update_wrapper(view, cls.dispatch, assigned=())
        return view   #最终还是返回函数
    
    def dispatch(self, request, *args, **kwargs):
        ..
            #根据请求方法判断
        if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)
    相关源码

    在类视图中使用装饰器

    我们知道在函数视图中,可以如下使用装饰器 

    def my_decorator(view_func):
        def wrapper(*args, **kwargs):
            print('装饰器被调用')
            return view_func(*args, **kwargs)
        return wrapper
    
    @my_decorator
    def func_demo(request):
        return HttpResponse('func_demo')
    函数视图使用装饰器

    在类视图中使用为函数视图准备的装饰器时,不能直接添加装饰器,需要使用method_decorator将其转换为适用于类视图方法的装饰器。

     

    类视图多继承& Minx扩展类

    使用面向对象多继承特性,可以通过定义父类(作为扩展类),在父类中定义想要想类视图补充的方法,类视图继承这些扩展类,便可实现代码服用。定义父类名称通常以Mixin结尾

    class ListModelMixin(object):
        """list扩展类"""
        def list(self, request, *args, **kwargs):
            print('查询多条数据')
    
    
    class CreateModelMixin(object):
        """create扩展类"""
        def create(self, request, *args, **kwargs):
            print('新增一条数据')
    
    
    class DepartmentView(CreateModelMixin, ListModelMixin, View):
        """
        同时继承两个扩展类,复用list和create方法
        """
        def get(self, request):
            self.list(request)
            return HttpResponse('get page')
    
        def post(self, request):
            self.create(request)
            return HttpResponse('post page')
    示例

    中间件

    Django中的中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出。中间件的设计为开发者提供了一种无侵入式的开发方式,增强了Django框架的健壮性。我们可以可以使用中间件,在Django处理视图的不同阶段对输入或输出进行干预。

    1、定义一个中间件,在项目中新建一个middlewares.py文件,然后在该文件中定义中间件类:

    from django.utils.deprecation import MiddlewareMixin
    
    
    # 定义中间件类: 通过继承Django的MiddlewareMixin扩展类实现
    class MyMiddleware(MiddlewareMixin):
    
        def __init__(self, get_response=None):
            # 服务器启动,初始化中间件类时被调用,只执行一次
            super().__init__(get_response)
            print('init')
    
        def process_request(self, request):
            print('before 视图')
            # 注意:可以返回None或者response对象,如果返回response对象,则视图函数就不会再执行了
    
        def process_response(self, request, response):
            print('after 视图')
            return response
    自定义中间件

    2、在settings.py文件中添加中间件

     

    3、定义一个视图进行测试

    def index(request):
        print('====index===')
        return HttpResponse('hello world')

     

    多个中间件的执行顺序

    #1、再定义一个中间件类
     class MyMiddleware2(MiddlewareMixin):
    
         def __init__(self, get_response=None):
             super().__init__(get_response)
             print('init 2')
    
         def process_request(self, request):
             print('before 视图 2')
    
         def process_response(self, request, response):
             print('after 视图 2')
             return response
    
    #2、注册
     MIDDLEWARE = [
         'django.middleware.security.SecurityMiddleware',
         ...
         'middlewares.MyMiddleware',  # 注册中间件
         'middlewares.MyMiddleware2',  
     ]
    
    #3、执行结果
     before 视图
     before 视图 2
     ==index==
     after 视图 2
     after 视图
    
    #4、结论
    对于视图之前执行的 process_request 方法,先 注册的中间件先执行
    对于视图之后执行的 process_response 方法,后 注册的中间件先执行
    示例说明
  • 相关阅读:
    关于有序查找的随笔
    Spring框架(一) 创建bean
    Linux常用命令
    Spring框架(二) bean的歧义性
    java实现图片文字识别的两种方法
    分享基于分布式Http长连接框架代码模型
    分享基于分布式Http长连接框架设计模型
    无限树Jquery插件zTree的使用方法
    分享基于分布式Http长连接框架
    使用vs编译事件来动态发布配置文件
  • 原文地址:https://www.cnblogs.com/sellsa/p/10745562.html
Copyright © 2011-2022 走看看