Class-based views是Django为解决建站过程中的常见的呈现模式而建立的。具有如下几个原则:
- 代码越少越好
- 永远不要重复代码
- View应当只包含呈现逻辑, 不应包括业务逻辑
- 保持view逻辑清晰简单
- 不要将CBVs用作403, 404, 500的错误处理程序
- 保持mixin简单明了
1. 使用django自身的cbvs
cbvs是可扩展的,但在也增加了复杂度,有时甚至出现8个import引入关系。django自带的view如下表所示:
类名 | 功能 | 例子 |
---|---|---|
View | 基本View, 可以在任何时候使用 | 见后面详细介绍 |
RedirectView | 重新定向到其他URL | 将访问"/log-in/"的用户重新定向到"/login/" |
TemplateView | 显示Django HTML template | 一般网站中使用模板显示的页 |
ListView | 显示对象列表 | 文章列表页 |
DetailView | 显示对象详情 | 文章详细页 |
FormView | 提交From | 网站联系我们或emai订阅form |
CreateView | 创建对象 | 创建新文章页 |
UpdateView | 更新对象 | 修改文章页 |
DeleteView | 删除对象 | 删除文章页 |
Generic date views | 显示一段时间内的对象 | 按时间归类的博客 |
2. View中基本元素
代码语言:javascript复制 1 class ModelCreatView(CreateView):
2 def __init__(self, model, template_name, context_object_name, success_url, success_msg, fields):
3 """
4 初始化函数,这里以creatview为例,其他view大同小异
5 :param model: 对应要操作的模型
6 :param template_name: 对应的模板名称,一般为html页面
7 :param context_object_name: 返回给前台的对象
8 :param success_url: 操作成功定向地址
9 :param success_msg: 返回的成功信息
10 :param fields: 需要操作的对应的模型中的属性
11 """
12 self.model = model
13 self.template_name = template_name
14 self.context_object_name = context_object_name
15 self.success_url = success_url
16 self.success_msg = success_msg
17 self.fields = fields
18 #
19 # self.model = MODEL
20 # self.fields = ['event_attribute', 'role_attribute', 'entiry_value', 'event_type', 'direction_flag', 'unique_flag',
21 # 'appear_flag']
22 # self.context_object_name = 'knowledgeGraph'
23 # self.success_url = '/knowledgeGraph/'
24 # self.template_name = 'knowledge_graph/add.html'
3. ListView简介
listview是一个展示列表的view,返回的是一个template,包含两个关键方法:
代码语言:javascript复制def get_context_data(self, **kwargs):
代码语言:javascript复制def get_queryset(self):
第一个方法返回一个字典给前端,包括分页信息,列表信息,已经其他自定义的信息;第二个方法返回数据库中获取到的数据(可能经过条件迭代),具体实现的实例代码如下:
代码语言:javascript复制 1 def get_context_data(self, **kwargs):
2 """
3 用来获取返回给前端页面的dict数据,前端页面可直接通过应用dict中的key来获取value
4 :param kwargs:
5 :return: context,一个字典类型的数据
6 """
7 try:
8 context = super(ModelListView, self).get_context_data(**kwargs)
9 log.debug("get_context_data")
10 page_obj = context['page_obj']
11 pages = []
12 for i in range(1, page_obj.paginator.num_pages 1):
13 if i == 1 or i == page_obj.paginator.num_pages:
14 pages.append(i)
15 elif i >= page_obj.number - 2 and i <= page_obj.number 2:
16 pages.append(i)
17 elif pages[-1] != None:
18 pages.append(None)
19 else:
20 pass
21 context['pages'] = pages
22 context['order_type'] = self.order_type
23 context['length'] = len(self.object_list)
24 if 'pagination_num' not in context:
25 context['pagination_num'] = self.paginate_by
26 self.echo_search(context)
27 if self.model == NodeData:
28 context['tree'] = self.get_tree()
29 return context
4. Mixin实现
view中如果觉得自带的post、get方法不够好,也可以重写post、get方法,这样就与函数式编程没有什么区别。有时需要前后端异步方式加载数据,就需要使用ajax来完成,这时就可以使用mixin来解决。
使用mixin可以为class提供额外的功能,但它自身却不能单独使用的类. 在具有多继承能力的编程语言中, mixin可以为类增加额外功能或方法. 在Django中, 我们可以使用mixin为CBVs提供更多的扩展性, 当然在类继承过程中, 我们推荐以下原则:
- Django自身提供的View永远在最右边
- mixin依次在以上view的左边
- mixin永远继承自Python的object类型
- 推荐mixin库django-braces
class ModelValidView(LoginRequiredMixin, AjaxResponseMixin, View):
def __init__(self, model):
self.model = model
def post_ajax(self, request, *args, **kwargs):
pass