CBV模式的接口
CBV模式即为API式的写法,一个资源类接受一系列的请求。本文讨论的是View的直接子类中的概念和方法,Django REST framework中重写和添加了大量的方法,可以直接继承自XXXAPIView,不再本文的讨论范围。
- 首先在试图函数中创建View的子类
- 在类中定义请求方式的类方法
- 在urlpatterns中添加方式不同,需要加as_view()
- 需要加(),调用这个方法
class HelloView(View):
def get(self, request):
return HttpResponse("GET view ok")
View中的方法
- __init__
- as_view
- dispaych
- http_method_not_allowed
- options
- __allowed_methods
- http_method_name
调用顺序为
as_view
- as_view
- as_view传入的参数不能和请求方法同名
def get(self, request):
return HttpResponse("GET %s" % self.msg)
- as_view传递进来的参数必须是类中既有的属性
- 定义view函数
- 创建自己的对象
def as_view(resquest):
def view(cls)
self = cls(**initkwargs)
- 记录传入的参数HelloView
- 只要支持get请求就支持head请求
- 在view函数中调用了dispatch
dispatch
- 根据请求方法名字小写取既有请求方法列表中判定
def dispatch(self, request, *args, **kwargs):
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)
- 如果请求不存在直接返回http_method_not_allowed
- 如果存在,会根据请求方法获取对应的属性
- 属性不存在也返回http_method_not_allowed
- 属性存在返回正常属性
- 调用属性
http_method_not_allowed
- 直接返回HttpResponse
_allowed_methods
- 用列表迭代器,返回请求方法的名字
return [m.upper() for m in self.http_method_names if hasattr(self, m)]
options
- 是一个请求方法
- 默认所有的CBV都支持options方法
类试图CBV流程
as_view
通过内置方法dispatch来分发请求方法
重写View父类,实现继承自重写类的类,可以支持请求方法
class HelloCustomView(object):
@classmethod
def as_view(cls):
def view(request):
self = cls()
return self.dispatch(request)
return view
def dispatch(self, request):
handler = getattr(self, request.method.lower(), None)
if not handler:
return HttpResponse("request method not allowed")
return handler(request)
def get(self, request):
return HttpResponse("GET")
def post(self, request):
return HttpResponse("POST")
def put(self, resquest):
return HttpResponse("PUT")
TemplateView
继承关系如图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gSkf4aVq-1573007279134)(github.com/belingud/im…)]
有三个父类
- TemplateResponseMixin
- ContextMixin
- View
- 用来分发请求的父类
TemplateResponseMixin
- 属性
- template_name
- template_engine
- response_class
- content_type
- 方法
- render_to_respose
- 将传入的上下文渲染形成响应
- get_template_names
- render_to_respose
- 作用
- 用来渲染模板的多继承类
ContextMixin
- 属性
- 方法
- get_context_data
- 作用
- 一个将传入的键值对转化为'view'键字典的默认多继承父类
View
- 属性
- http_method_names
- 方法
- as_view
- view
- dispatch
- http_method_not_allowed
- options
- as_view
- 作用
- 用来分发请求
TemplateView实现的功能:
- 分发请求:dispatch方法
- 实现了get请求:在TemplateView类中的get方法
- 获取上下文:ContextMixin多继承父类
- 渲染成响应:TemplateResponseMixin中的render_to_respose方法
ListView
继承关系如图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BIF0IjzQ-1573007279135)(github.com/belingud/im…)]
ListView只是继承父类,没有在其中增改方法
有两个父类:
- MultipleObjectTemplateResponseMixin
- BaseListView
MultipleObjectTemplateResponseMixin的属性和方法
属性:
- template_name_suffix = '_list'
方法:
- def get_template_names(self):返回模板名字的列表
BaseListView的属性和方法
无属性
方法:
- get():将传入的上下文渲染成响应,默认支持get请求
return self.render_to_response(context)
MultipleObjectTemplateResponseMixin
有一个父类
TemplateResponseMixin
也是View的父类,属性和方法同上文的TemplateResponseMixin
BaseListView
有两个父类
- MultipleObjectMixin
他有一个父类ContextMixin,父类的类方法 get_context_data 将传入的键值对转化为’view’键字典的默认多继承父类
属性:
- allow_empty
- context_object_name
- model
- ordering
- 以某个字段排序,可以制定多个
- page_kwargs
- paginate_by
- paginate_class
- paginate_orphans
- queryset
传入一个model或者query_set,返回modelname_list,否则默认为object_list
model = Book # 或下面的query_set
queryset = Book.objects.all()
方法:
- get_queryset
- get_ordering
- paginate_queryset
- get_paginate_by
- get_paginator
- get_paginate_orphans
- 返回最后一个页码
- get_allow_empty
- get_context_object_name
- get_context_data
- 用来重写
即上文中的View
流程概览
graph LR
A[url] --> B[as_views]
B[as_views]-->C[dis_patch]
C[dis_patch]-->D[get]
D[get]-->E[get_queryset]
E[get_queryset]-->F[get_context_data]
F[get_context_data]-->G[render_to_response]
graph TD
A[get_queryset]-->B[queryset属性和model属性]
A[get_queryset]-->C[get_ordering]
A[get_queryset]-->D[get_allow_empty]
graph TD
A[get_context_data]-->B[get_paginate_by]
A[get_context_data]-->C[get_context_object_name]
A[get_context_data]-->D[向context中注入数据]