多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## 一、类视图 * 发帖功能 ~~~ # url配置 urlpatterns = [ url(r'^post$', views.post), # 显示发帖界面 url(r'^do_post$', views.do_post), # 执行发帖操作 ] # 视图 def post(request): """get请求: 显示发帖界面""" return render(request, 'post.html') def do_post(request): """post请求: 执行发帖操作""" title = request.POST.get('title') content = request.POST.get('content') return HttpResponse('发帖:title=%s, content=%s' % (title, content)) ~~~ * 通过一个URL和视图同时实现登录功能的`GET`和`POST`请求(注意:可能还有`PUT``DELETE`等); ~~~ # url配置 urlpatterns = [ url(r'^post$', views.post), # 发帖功能 ] # 视图 def post(request): """发帖功能""" if request.method == 'GET': # get请求: 显示发帖界面 return render(request, 'post.html') else: # post请求: 执行发帖操作 title = request.POST.get('title') content = request.POST.get('content') return HttpResponse('发帖:title=%s, content=%s' % (title, content)) ~~~ * **类视图**实现 * 以函数的方式定义的视图称为**函数视图** * 在Django中还可以通过类来定义一个视图,称为**类视图** * **类视图**的使用 1. 定义一个类,继承Django提供的`View`类 ~~~ from django.views.generic import View class PostView(View): def get(self, request): """get请求: 显示发帖界面""" return render(request, 'post2.html') def post(self, request): """post请求: 执行发帖操作""" # 代码简略 return HttpResponse('执行发帖操作') ~~~ 2. 调用类视图的`as_view()`方法配置url ~~~ urlpatterns = [ ... # 类视图注册 url(r'^post2$', views.PostView.as_view()), ] ~~~ * 类视图优点:**对于函数视图代码可读性和复用性更好** ## 二、类视图原理 ~~~ @classonlymethod def as_view(cls, **initkwargs): """ Main entry point for a request-response process. """ ...省略代码... def view(request, *args, **kwargs): self = cls(**initkwargs) if hasattr(self, 'get') and not hasattr(self, 'head'): self.head = self.get self.request = request self.args = args self.kwargs = kwargs # 调用dispatch方法,按照不同请求方式调用不同请求方法 return self.dispatch(request, *args, **kwargs) ...省略代码... # 返回真正的函数视图 return view def dispatch(self, request, *args, **kwargs): # Try to dispatch to the right method; if a method doesn't exist, # defer to the error handler. Also defer to the error handler if the # request method isn't on the approved list. 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) ~~~ ## 三、类视图使用装饰器 ### 1\. 函数视图使用装饰器 需求: 实现禁止ip黑名单访问发帖界面。 解决: 可以通过在视图函数中使用装饰器实现,如下 1. **为函数视图定义一个装饰器**(在设计装饰器时,基本都以函数视图作为考虑的被装饰对象) ~~~ def check_ip(view_fun): """装饰器:禁止黑名单ip访问""" def wrapper(request, *args, **kwargs): # 在视图函数执行前做额外的操作: # 禁止ip黑名单访问 IP = request.META.get('REMOTE_ADDR') if IP in ['192.168.210.160']: return HttpResponse('IP禁止访问') return view_fun(request, *args, **kwargs) return wrapper ~~~ 2. 给视图函数进行装饰 ~~~ @check_ip def post(request): """GET请求: 显示发帖界面""" return render(request, 'post.html') ~~~ **或者:**也可以在URL中,通过方法调用的方式添加装饰器 ~~~ urlpatterns = [ ... # 发帖功能 url(r'^post$', check_ip(views.post)) ] ~~~ * 问题:代码可读性差,只看视图,不知道它添加了装饰器 ### 2\. 类视图中使用装饰器 **方案一:在路由中添加** ~~~ ```python urlpatterns = [ ... # 发帖功能 url(r'^post2$', check_ip(views.PostView.as_view())) ] ``` ~~~ **方案二:在类视图中添加** 注意:**不能直接给类视图的方法添加装饰器**,需要使用**method\_decorator**将其转换为适用于类视图方法的装饰器。 ~~~ # 方式二 # @method_decorator(check_ip, name='get') # 为特定的请求方法添加 # @method_decorator(check_ip, name='dispatch') # 为所有的请求方法添加 class PostView(View): # 给所有的http方法都添加装饰器 # @method_decorator(check_ip) def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) # 方式一 @method_decorator(check_ip) def get(self, request): """get请求:显示发帖界面""" return render(request, 'post2.html') def post(self, request): """post请求:执行发帖操作""" # 代码简略 return HttpResponse('处理发帖操作') ~~~ **说明: 关于method\_decorator装饰器作用:**为函数装饰器补充第一个self参数,以便让装饰器能应用到方法中。 ### 3\. 类视图多继承 & Mixin扩展类 使用面向对象多继承的特性,可以通过定义父类(作为扩展类),在父类中定义想要向类视图补充的方法,类视图继承这些扩展父类,便可实现代码复用。 定义的扩展父类名称通常以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) ... def post(self, request): self.create(request) ... class EmployeeView(CreateModelMixin, View): """ 继承CreateModelMixin扩展类,复用create方法 """ def post(self, request): self.create(request) ... ~~~