django-CBVS (转载知乎彧神)
来源:互联网 发布:哪个网站有卖淘宝小号 编辑:程序博客网 时间:2024/05/17 07:25
稍微改了下格式 ==
链接:https://www.zhihu.com/question/25339933/answer/32104394
我觉得要理解django的class-based-view(以下简称cbv),首先要明白django引入cbv的目的是什么。在django1.3之前,generic view也就是所谓的通用视图,使用的是function-based-view(fbv),亦即基于函数的视图。有人认为fbv比cbv更pythonic,窃以为不然。
python的一大重要的特性就是面向对象。而cbv更能体现python的面向对象。cbv是通过class的方式来实现视图方法的。class相对于function,更能利用多态的特定,因此更容易从宏观层面上将项目内的比较通用的功能抽象出来。关于多态,不多解释,有兴趣的同学自己Google。
总之可以理解为一个东西具有多种形态(的特性)。cbv的实现原理通过看django的源码就很容易明白,大体就是由url路由到这个cbv之后,通过cbv内部的dispatch方法进行分发,将get请求分发给cbv.get方法处理,将post请求分发给cbv.post方法处理,其他方法类似。怎么利用多态呢?cbv里引入了mixin的概念。
Mixin就是写好了的一些基础类,然后通过不同的Mixin组合成为最终想要的类。所以,理解cbv的基础是,理解Mixin。我们以1.5为例简单讲解一下Mixin。
在python-path/Lib/site-packages/django/view/generic
文件夹下,包含了django自带的几个基于类的通用视图。base.py:ContextMixin: 提供get_context_data方法,给cbv提供context_dataView: cbv的基类,提供视图分发等功能TemplateResponseMixin: 提供渲染模板等功能
TemplateView(TemplateResponseMixin, ContextMixin, View): 从类的构造上就可以看出,这个类是由TemplateResponseMixin,ContextMixin,View三个类共同继承而来的,所以同时具有这三个类的特定,因此,这个类完整的提供了一个cbv应该具有的所有动作(除了处理数据)。
RedirectView(View): 这是View的一个子类,实现的是重定向的功能。base中已经提供了构成cbv最最基础的几个Mixin,以及cbv的基类View。以下django又提供了detail,list,edit,dates四个模块,这四个模块分别用来处理detail数据(比如显示日志的某一篇的明细信息),list(比如显示某user的所有日志列表),edit(比如为用户提供新增日志和修改日志的功能),dates(比如显示2014年10月的日志)。想一下,从数据维度上讲,默认的django cbv提供了按照数据维度处理的两个不同的cbv,分别是detail和list。detail显示一个数据对象,list显示数据列表。
下面先分析detail.py:SimpleObjectMixin(ContextMixin): 这是ContextMixin的一个子类,提供最基础的取回单个对象的功能。BaseDetailView(SimpleObjectMixin, View): 提供显示单个对象的功能。SimpleObjectTemplateResponseMixin(TemplateResponseMixin): 这是对TemplateResponseMixin的再次封装,为了实现单个对象的模板显示。DetailView(SimpleObjectTemplateResponseMixin, BaseDetailView): 这就是完整的detail view了。
从以上类的继承上就可以大致猜出,detail模块中的相关cbv其实是对base中提供的mixin的再度继承。从而实现更精细复杂的功能。所以剩下几个模块题主完全可以自己分析了。所以分析完了各个模块提供的功能就完了吗?如果到这里止步,那么还是不了解cbv的好处。上文说过,cbv的一大好处就是多态。因此可以把通用的功能抽象出来做成mixin给其他cbv用。比如,想实现restful API。最简单的,想实现返回json数据。写一个mixin就好了。class JSONResponseMixin(object):
“”“JSON mixin”“”
def render_to_response(self, context): return self.get_json_response(self.convert_context_to_json(context)) def get_json_response(self, content, **httpresponse_kwargs): return HttpResponse(content, content_type='application/json', **httpresponse_kwargs) def convert_context_to_json(self, context): return json.dumps(context)
怎么用呢?
class CheckRemindUtilView(JSONResponseMixin, ListView): """ Check if there is reminder need to be reminded. This view should be called every minute. """ def get_queryset(self): start = timezone.now() end = start + datetime.timedelta(minutes=1) return Reminder.objects.filter(next_t__gte=start, next_t__lte=end, is_valid=True) def get(self, request, *args, **kwargs): self.object_list = self.get_queryset() if (self.get_paginate_by(self.object_list) is not None and hasattr(self.object_list, 'exists')): is_empty = not self.object_list.exists() else: is_empty = len(self.object_list) == 0 if is_empty: ret = {'code': 42, 'msg': 'empty'} else: for object_ in self.object_list: code = exec_remind(object_) object_.previous_t = object_.next_t update_reminder(object_) ret = {'code': code, 'msg': 'reminded.'} return self.render_to_response(ret)
再从另一个方向举个栗子。比如需要对日志进行用户过滤,用户私有的日志只能用户自己看到,其他人看不到。那么只需要写一个PrivateObjectMixin,然后其他DetailView,ListView继承这个就好了。
class PrivateObjectMixin(object): ''' Filter private object for request.user ''' def filte_private(self, queryset): ''' Filte private object for authenticated user. ''' ordering = getattr(self, 'ordering', '-date_created') if not hasattr(self, 'request'): return queryset if not hasattr(self.request, 'user'): return queryset if self.request.user.is_authenticated(): queryset = queryset.filter(Q(is_valid=True), Q(is_private=True) & Q(user__id=self.request.user.id) | Q(is_private=False)) else: queryset = queryset.filter(is_valid=True, is_private=False) try: result = queryset.order_by(ordering) except FieldError: # The model doesnot have an `ordering` field. return queryset return resultclass NoteListView(PrivateObjectMixin, BaseNoteListView): ''' Show note list. ''' def get_queryset(self): ''' Get notes. ''' queryset = Note.objects.all() return self.filte_private(queryset)
上面这两个例子只是简单的应用而已,完全可以借助多态实现更复杂的cbv。以下是建议部分:
1,建议翻阅django cbv的源码,自己画个图了解cbv的实现原理,继承流程。
2,自己写几个简单的cbv。
私货部分:有个django的伪专家群:69930365
基于django(django-rest-framework)的个人站:今人不见古时月
- django-CBVS (转载知乎彧神)
- Django 1.6 CBVs
- Django 1.6 最佳实践: 如何正确使用 CBVs (Class-based views)
- [转载]安装配置Django开发环境(Eclipse + Pydev)
- django web Cookie 和 Sessions 应用(转载)
- 转载:安装配置Django开发环境(Eclipse + Pydev)
- django中的request.META字典(部分转载)
- (转载)django工作原理简介
- (转载)获取Django中model字段名 字段的verbose_name
- django的安装及web部署(转载)
- 【转载】Django model字段类型清单
- django中的ajax实现(POST)--转载备份
- django中的ajax实现(GET)--转载备份
- 【转载】django web Cookie 和 Sessions 应用
- 【转载】 linux-mysql-django…
- django(一)--- 安装django
- 【Django】Django 定时任务实现(django-crontab+command)
- 转载使用PyAmf来实现Flex与Django的通信
- 约束:确保数据的完整性(主键,唯一,检查,默认,非空,外键)
- Why doesn't `sudo cd /var/named` work?
- 图像边缘检测原理&何谓角点及Harris角点的基本原理&SURF特征提取简介
- 所有的经历都是为了更好的前行
- int、bigint、smallint 和 tinyint范围
- django-CBVS (转载知乎彧神)
- 7.1 方法
- lua C API
- Java NIO系列教程(四) Scatter/Gather
- 9.Selenium2 自动化测试实战-基于Python语言-键盘事件
- 剑指offer-树的子结构
- RTP Payload H264
- C#中引用传递与指针传递区别
- 关于资源文件R