- RESTful 规范
- django rest framework 之 认证(一)
- django rest framework 之 权限(二)
- django rest framework 之 节流(三)
- django rest framework 之 版本(四)
- django rest framework 之 解析器(五)
- django rest framework 之 序列化(六)
- django rest framework 之 分页(七)
- django rest framework 之 视图(八)
在之前的django rest framework
其他组件中,在视图函数中继承类都是rest_framework.view.APIView
,这个APIView
是继承的django
中的View
并且做了封装和方法重写的。 那么在django rest framework
中,还有有没有提供其他的类能够继承?
一、GenericAPIView
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
的内部的一些方法会根据会自动的获取数据库查询结果并分页和序列化。
- get_queryset(): 会获取数据库查询结果,也就是
queryset
- paginate_queryset(roles):会根据重写的
pagination_class
属性获取分页类进行分页操作,另外如果这里没有重写,会自动到settings.py
配置文件去找 - self.get_serializer():就是根据分页后的对象进行数据的序列化,也会先找到序列化类
二、GenericViewSet
1、源码分析
GenericViewSet
实际上使用了多继承和Mixin
模式,也就是说GenericViewSet
同时继承了ViewSetMixin, generics.GenericAPIView
两个父类
# rest_frameworkviewsets.py 源码
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
pass
在GenericViewSet
中由于类继承的先后顺序的关系,会先执行ViewSetMixin
类中相关方法。而GenericAPIView
类中的相关方法会被忽略。
2、路由
在执行之前要更改一下路由系统
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
请求。
3、视图
视图中基本上和上面一样,只不过更改了不同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)
4、测试
<1>、测试一
http://127.0.0.1:8000/api/genericset
,get
方法获取数据时,返回正常结果
<2>、测试二
http://127.0.0.1:8000/api/genericset/
,表示发送post请求添加单条数据,数据添加成功
三、ModelSetView
1、源码分析
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,
分别对应,创建,获取单条数据,更新,删除,或许多条数据。
2、路由
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中增加正则匹配。
3、视图
在视图中,并没有增加相应的增删改查的逻辑却能完成相应的功能,这是因为继承的mixin
类中,已经有一一对应的方法,视图类会自动调用父类的方法。
from rest_framework.viewsets import ModelViewSet
class ModelSetView(ModelViewSet):
queryset = Role.objects.get_queryset().order_by('id')
serializer_class = PagerSerializer
pagination_class = PageNumberPagination
获取第九条数据,返回结果
4、自定义
在ModelSetView
中看到,继承了多个mixin
类,而这些类又分别封装了不同的对应于增删给查的方法,因此如果想要自定义一个接口,实现部分http方法,就可以根据需要继承不同的mixin
类
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,