【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风格(逃
