第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')
路由那里,我则需要使用该视图的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 方法,后 注册的中间件先执行
每天进步一点,加油!