您的位置:首页 > 编程语言 > Go语言

Django Rest Framework----ModelViewSet视图 ModelViewSet源码分析

2018-06-22 10:08 771 查看

一、视图类

#bookview是一个视图类,继承自ModelViewSet
class BookView(ModelViewSet):
throttle_classes = [VisitThrottle2]
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer


ModelViewSet

ModelViewSet:
class ModelViewSet(mixins.CreateModelMixin,    # 实现了post添加逻辑
mixins.RetrieveModelMixin,          # 实现了获取具体某一本书的逻辑
mixins.UpdateModelMixin,            # 实现了put编辑的逻辑
mixins.DestroyModelMixin,           # 实现了删除一本书的逻辑
mixins.ListModelMixin,              # 实现了获取所有书的逻辑
GenericViewSet):                    # 提供了APIView和dispatch的功能
....


由于ModelViewSet继承了多个混合类和通用视图类,所以ModelViewSet提供了.list(),.retrieve(), .create(),.update(),.partial_update(),和.destroy()
因为ModelViewSet继承了GenericViewSet,所以BookView需要提供queryset和serializer_class属性


二、执行流程

1. url:

url(r'books/$',views.BookView.as_view({'get':'list','post':'create'})),
url(r'books/(?P<pk>\d+)/$',views.BookDetailView.as_view({'get': 'retrieve',
'put':'update',
'delete':'destroy'})),


当django启动的时候,会执行view.BookView.as_view()方法:由于as_view()是从ViewSetMixin中继承而来的,所以url会变为:

url(r'books/$',ViewSetMixin.view),
url(r'books/(?P<pk>\d+)/$',ViewSetMixin.view),


2.当用户访问books/的时候,会调用执行ViewSetMixin.view并传入request。

class ViewSetMixin(object):
"""
他是一个魔法方法
重写`.as_view()‘,以便它接受一个’actions‘关键字,
该关键字执行HTTP方法到资源上的操作的绑定。
例如,要创建一个将“GET”和“POST”方法绑定到“List”和“Create”操作的具体视图.
view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
"""
def view(request, *args, **kwargs):
self = cls(**initkwargs)
self.action_map = actions

# {'get':'list','post':'create'}
# {'get': 'retrieve','put':'update','delete':'destroy'}

for method, action in actions.items():
# self:ModelViewSet继承的每一个类 action是list create等方法。
# handler是每一个具体的函数名
handler = getattr(self, action)
#为属性赋值, self.get = list, self.get = retrieve
# 当get请求的时候,真正会执行的是list/retrieve方法
setattr(self, method, handler)

# 进行分发,由于以上几个类都没有实现该方法,所以dispatch()执行的是APIView的dispatch()
return self.dispatch(request, *args, **kwargs)


3.ViewSetMixin的view主要是把mixins中的list()、create()、retrieve()、等绑定给BookView的get()、post()等。

4.dispatch()

def dispatch(self, request, *args, **kwargs):

try:
self.initial(request, *args, **kwargs)

# get、put、post等请求方法,去list、create、update等,去执行
if request.method.lower() in self.http_method_names:

# 这里的self是ViewSetMixin。
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed

response = handler(request, *args, **kwargs)

except Exception as exc:
response = self.handle_exception(exc)

self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response


当客户端请求方式是get的时候,执行BookView的get()方法,实际上是执行的list().因为在ViewSetMixin.view()中,获取minx下的list、create等函数地址,通过settattr()的方式绑给了BookView实例对象

三、总结:

django启动******

url(r'books/$',views.BookView.as_view({'get':'list','post':'create'})),   1
url(r'books/$',ViewSetMixin.view)),    2

一旦用户访问******

books  get请求

def view(request, *args, **kwargs):
self = cls(**initkwargs)
{'get':'list','post':'create'}

for method, action in actions.items():

handler = getattr(self, action)
#给BookView设置一个属性  BookView.get = ListModelMixin.list
setattr(self, method, handler)

return self.dispatch(request, *args, **kwargs)

url(r'books/$',APIView.dispatch)),  3

if get in self.http_method_names:

# 这里的self是ViewSetMixin。
handler = getattr(self, 'get'),  --> BookView.get ---> 实际上执行的是 ListModelMixin.list
self.http_method_not_allowed)

handler返回什么,dispatch返回什么,view返回什么,用户看到什么
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: