在以前的django rest framework
其余组件中,在视图函数中继承类都是rest_framework.view.APIView
,这个APIView
是继承的django
中的View
而且作了封装和方法重写的。 那么在django rest framework
中,还有有没有提供其余的类可以继承?html
GenericAPIView
在django rest framework
中根据APIView
又作了一层封装。则继承关系就变成了GenericAPIView——>APIView——>View
数据库
from rest_framework.generics import GenericAPIView class GenericView(GenericAPIView): queryset = Role.objects.get_queryset().order_by('id') serializer_class = PagerSerializer pagination_class = PageNumberPagination def get(self,request,*args,**kwargs): roles = self.get_queryset() pager_roles = self.paginate_queryset(roles) ser = self.get_serializer(instance=pager_roles,many=True) return Response(ser.data)
这里实现的功能和django rest framework
之 分页中的功能同样,先获取数据,分页,序列化返回。不一样的是,这里因为封装的做用,GenericAPIView
的内部的一些方法会根据会自动的获取数据库查询结果并分页和序列化。django
queryset
pagination_class
属性获取分页类进行分页操做,另外若是这里没有重写,会自动到settings.py
配置文件去找GenericViewSet
实际上使用了多继承和Mixin
模式,也就是说GenericViewSet
同时继承了ViewSetMixin, generics.GenericAPIView
两个父类api
# rest_framework\viewsets.py 源码 class GenericViewSet(ViewSetMixin, generics.GenericAPIView): pass
在GenericViewSet
中因为类继承的前后顺序的关系,会先执行ViewSetMixin
类中相关方法。而GenericAPIView
类中的相关方法会被忽略。app
在执行以前要更改一下路由系统iview
from django.conf.urls import url from .views import * app_name = 'api' urlpatterns = [ url(r'^generic/$', GenericView.as_view()), url(r'^genericset/$', GenericSetView.as_view({'get': 'list', 'post': 'create'})), ]
因为在GenericViewSet
的内部重写了as_view
方法,且继承关系又先于GenericAPIView
类,因此会进入GenericViewSet
的as_view
方法。可是在as_view
方法中,对路由系统作了略微的改动,须要对方法,作一一映射关系。即'get': 'list', 'post': 'create',get
(获取单条数据)请求,会进入子类的list
方法,而create
(建立对象)方法则表明了post
请求。函数
视图中基本上和上面同样,只不过更改了不一样http请求方法的对应类方法名源码分析
from rest_framework.viewsets import GenericViewSet class GenericSetView(GenericViewSet): queryset = Role.objects.get_queryset().order_by('id') serializer_class = PagerSerializer pagination_class = PageNumberPagination def list(self,request,*args,**kwargs): # 获取数据 roles = self.get_queryset() # models.Role.objects.all() # [1, 1000,] [1,10] pager_roles = self.paginate_queryset(roles) # 序列化 ser = self.get_serializer(instance=pager_roles,many=True) return Response(ser.data) def create(self, request, *args, **kwargs): ret = {} try: title = request.data['title'] Role.objects.create(title=title) print('success') except Exception as e: print(e)
http://127.0.0.1:8000/api/genericset
,get
方法获取数据时,返回正常结果post
http://127.0.0.1:8000/api/genericset/
,表示发送post请求添加单条数据,数据添加成功测试
ModelSetView
作的更完全,他又一次继承了GenericViewSet
,而且在此以前又继承了其余几个类,所以功能更多,变成了ModelViewSet——>GenericViewSet——>APIView——>View
class ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet): pass
从这些类的名字能够大概看出,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,.ListModelMixin,
分别对应,建立,获取单条数据,更新,删除,或许多条数据。
from django.conf.urls import url from django.urls import path from .views import * app_name = 'api' urlpatterns = [ url(r'^modelset/(?P<pk>\d+)/$', ModelSetView.as_view({'get': 'retrieve','delete':'destroy','put':'update','patch':'partial_update'})), ]
因为在获取,删除,更新数据的时候须要这顶数据的惟一标识,这里是pk主键,所以须要在url中增长正则匹配。
在视图中,并无增长相应的增删改查的逻辑却能完成相应的功能,这是由于继承的mixin
类中,已经有一一对应的方法,视图类会自动调用父类的方法。
from rest_framework.viewsets import ModelViewSet class ModelSetView(ModelViewSet): queryset = Role.objects.get_queryset().order_by('id') serializer_class = PagerSerializer pagination_class = PageNumberPagination
获取第九条数据,返回结果
在ModelSetView
中看到,继承了多个mixin
类,而这些类又分别封装了不一样的对应于增删给查的方法,所以若是想要自定义一个接口,实现部分http方法,就能够根据须要继承不一样的mixin
类
mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin,