【Django】cbv是个好东西
原标题: 这两天摸鱼所得
将狗里cbv与fbv的优劣不阐述, cbv的多态继承与python这种oo语言风格上就保持了一致, 无论是呈现逻辑(View)与业务逻辑(Mixin)都能很好的进行拼接, 更别说有大量的第三方扩展了
1.CBVs的使用原则
代码越少越好
永远不要重复代码
View应当只包含呈现逻辑, 不应包括业务逻辑
保持view逻辑清晰简单
不要将CBVs用作403, 404, 500的错误处理程序
保持mixin简单明了
2.如何使用mixin
在编程中mixin是指为继承它的class提供额外的功能, 但它自身却不能单独使用的类. 在具有多继承能力的编程语言中, mixin可以为类增加额外功能或方法. 在Django中, 我们可以使用mixin为CBVs提供更多的扩展性, 当然在类继承过程中, 我们推荐以下原则:
Django自身提供的View永远在最右边
mixin依次在以上view的左边
mixin永远继承自Python的object类型
3.减少重复砌砖头?来看看通用视图
为了深入了解Django的通用view, 到了痛苦地读源码(文末附)的时候了. 当然如果你不写Django也不妨看看, 读一读或许对模板系统的理解有所启发
来来来我们进入Django.views.generic (anyway), 从简到繁
base.py
颜料盒base.py
class | Super | Docs |
---|---|---|
ContextMixin | object | A default context mixin that passes the keyword arguments received by get_context_data as the template context. |
View | object | Intentionally simple parent class for all views. Only implements dispatch-by-method and simple sanity checking. |
TemplateResponseMixin | object | A mixin that can be used to render a template. |
TemplateView | ContextMixin, TemplateResponseMixin, View | A view that renders a template. This view will also pass into the context any keyword arguments passed by the URLconf. |
RedirectView | View | A view that provides a redirect on any GET request. |
三个继承Object
的初始class, 这就好比绘图使用的三原色, 后面大部分的Mixin和View都是由它们变化而来. 其中:
ContextMixin
包含一个get_context_data
方法, 用于渲染模板数据
View
是通用View,包含一个as_view
的req到res响应方法, 提供http方法及其允许列表, 进行一些简单的检查
TemplateResponseMixin
是用于渲染模板的方法, 包括指定模板路径和渲染引擎
这个TemplateView
是个简单的模板View, 继承与上面三个对象, 定义了render_to_response
, 相当于静态页面 (从fbv转过来的童鞋用这个View并且重写get_context_data方法就能完成简单的fbv->cbv的转换了)
RedirectView
重定向View, 重写了get
, 只需要处理GET请求的view, 使用url
参数指定重定向页面
detail.py
detail.py里定义了一系列对象信息展示的view, 核心View是最后的DetailView
class | Super | Docs |
---|---|---|
SingleObjectMixin | ContextMixin | Provides the ability to retrieve a single object for further manipulation. |
BaseDetailView | SingleObjectMixin, View | A base view for displaying a single object |
SingleObjectTemplateResponseMixin | TemplateResponseMixin | - |
DetailView | SingleObjectTemplateResponseMixin, BaseDetailView | Render a “detail” view of an object. By default this is a model instance looked up from self.queryset , but the view will support display of any object by overriding self.get_object() . |
SingleObjectMixin
扩展了ContextMixin
, 使其能够使用model,query等获取对象, 然后通过设置定义的context_object_name
去渲染模板内定义的字段
BaseDetailView
在view
上使用了SingleObjectMixin
, 给get
方法添加了将对象转化为context
(上下文)的操作, 使其成为一个能够请求处理对象的基础view, 但是还没有渲染方法, 不设置的原因是还能够绑定删除mixin成为BaseDeleteView
SingleObjectTemplateResponseMixin
无说明, 但是从代码上看是除了渲染方法以外,额外定义默认对象渲染模板名称 默认页面后缀_detail
这个方法多次复用于base类view, 给基础对象处理类view提供渲染方法
DetailView
详情View, 单纯地继承BaseDetailView
和SingleObjectTemplateResponseMixin
list.py
list.py用于展示列表, 写法与detail.py
类似, 核心View是ListView
class | Super | Docs | |
---|---|---|---|
MultipleObjectMixin | Context | A mixin for views manipulating multiple objects. | |
BaseListView | MultipleObjectMixin, View | A base view for displaying a list of objects. | |
MultipleObjectTemplateResponseMixin | TemplateResponseMixin | Mixin for responding with a template and list of objects. | |
ListView | MultipleObjectTemplateResponseMixin, BaseListView | Render some list of objects, set by self.model or self.queryset . self.queryset can actually be any iterable of items, not just a queryset. |
MultipleObjectMixin
与SingleObjectMixin
不同的方式扩展了ContextMixin
, 使其能够使用model等获取queryset之外, 额外提供了页面分页功能及其参数和方法
BaseListView
是一个能够请求处理对象列表的基础view, 但是还没有渲染方法
MultipleObjectTemplateResponseMixin
功能都差不多..
ListView
单纯继承上面两个
edit.py
edit.p涉及了CRUD, 所以引入了form
的概念, 核心View为CreateView
,UpdateView
,DeleteView
,这里的View比较耳熟吧
class | Super | Docs |
---|---|---|
FormMixinBase | type | - |
FormMixin | six.with_metaclass(FormMixinBase, ContextMixin) | A mixin that provides a way to show and handle a form in a request. |
ModelFormMixin | FormMixin, SingleObjectMixin | A mixin that provides a way to show and handle a modelform in a request. |
ProcessFormView | View | A mixin that renders a form on GET and processes it on POST. |
BaseFormView | FormMixin, ProcessFormView | A base view for displaying a form |
FormView | TemplateResponseMixin, BaseFormView | A view for displaying a form, and rendering a template response. |
BaseCreateView | ModelFormMixin, ProcessFormView | Base view for creating an new object instance. Using this base class requires subclassing to provide a response mixin. |
CreateView | SingleObjectTemplateResponseMixin, BaseCreateView | View for creating a new object instance, with a response rendered by template. |
BaseUpdateView | ModelFormMixin, ProcessFormView | Base view for updating an existing object. Using this base class requires subclassing to provide a response mixin. |
UpdateView | SingleObjectTemplateResponseMixin, BaseUpdateView | View for updating an object, with a response rendered by template. |
DeletionMixin | object | A mixin providing the ability to delete objects |
BaseDeleteView | DeletionMixin, BaseDetailView | Base view for deleting an object. Using this base class requires subclassing to provide a response mixin. |
DeleteView | SingleObjectTemplateResponseMixin, BaseDeleteView | View for deleting an object retrieved with self.get_object() , with a response rendered by template. |
注: six是一个python2和python3兼容库.
FormMixinBase
继承type定义了一个类型, 重写了__new__
, 内容暂时看不懂:)
FormMixin
表单逻辑, 这里就定义了几个重要的属性和方法, 用户使用formform_class
, 成功回调urlsuccess_url
表单合法form_valid
表单不合法form_invalid
等
ModelFormMixin
进一步扩展FormMixin
, 提供fields
字段使用户能够处理ModelForm
, form_valid
中添加了保存操作
ProcessFormView
功能View, 重写了View
的get和post方法(put直接return post方法) 使View能够在get的时候 渲染form内容, post的时候能提交form内容
BaseFormView
相当于给ProcessFormView
提供了表单处理逻辑, 相当于能处理一些简单的请求了
FormView
继续给BaseFormView
加上模板渲染引擎, 处理结果能从前台渲染出来了
BaseCreateView
和BaseFormView
类似, 不过其使用的是modelForm, form_valid
会调用form.save()
方法, get
和post
中执行了一句self.object = None
其作用于SingleObjectMixin
的get_context_data
方法中 (detail.py 103-107行,判断self.object不为空时执行取址操作 v1.9.5)
CreateView
单纯基础BaseCreateView
和SingleObjectTemplateResponseMixin
,别忘了后者只是是一个轻度继承的渲染工具 默认页面后缀_form
BaseUpdateView
和BaseCreateView
代码几乎相同, 除了self.object = None
改为self.object = self.get_object()
作用于相同位置, 进行字典更新操作
UpdateView
单纯基础BaseUpdateView
和SingleObjectTemplateResponseMixin
默认页面后缀_form
DeletionMixin
新的颜料,因为功能使用不频繁所以单独放在这里, 提供了delete
方法和success_url
属性, delete
执行self.object.delete()
后会自动执行页面回调. 特别注意的是, 这里只有post
方法return了delete
方法, 其他方法暂不支持
BaseDeleteView
给BaseDetailView
绑定删除功能, 仅简单继承, 无页面渲染 简单的删除后跳转
DeleteView
单纯继承BaseDeleteView
和SingleObjectTemplateResponseMixin
, 默认页面后缀_confirm_delete
, 给一个删除页面, get即渲染一个页面, 给个表格, post到这个页面后将删除对象
dates.py
这是一个基于时间的页面通用view模板, 但是除了博客之类的基本上用不着, 不阐述.
假装参考
(这篇博文原意是好的, 但是读着感觉变成django-braces
文档了, 那我为啥不去看源文档呢呢)
这些通用view的具体简单实例.
本文源码 顺带一提 Django中admin还是保持fbv风格(逃