视图集
在使用扩展的Mixin时,我们可以发现,仍然有部分代码重复,这就意味着还有可以简化程序的可能。这就引申除了视图集这个概念,即将对数据的五种操作:
- list()提供一组数据
- retrieve()提供单个数据
- create()创建数据
- updata()修改并保存数据
- destroy()删除数据
ViewSet视图集类中不再实现get(),post()等方法,而是实现工作action,如list(),create()等。
视图集只在使用as_view()方法的时候,才会将动作与具体请求方式对应上。即以字典的方式告知as_view()调用方法
class BookInfoViewSet(viewsets.ViewSet):
def list(self, request):
...
def retrieve(self, request, pk=None):
...
在设置路由时,可以在as_view()方法中使用字典的格式,告知序列化器,使用何种请求方式调用哪个方法
urlpatterns = [
url(r'^books/$', BookInfoViewSet.as_view({'get':'list'}),
url(r'^books/(?P<pk>\d+)/$', BookInfoViewSet.as_view({'get': 'retrieve'})
]
- 在这里,as_view中的{‘get’:‘list’},get就是我们想要调用的请求方式,list,就是我们要调用的方法,系统默认提供了list(),create(),update(),retrieve()和destroy()这五个方法。
- 除此之外,我们还可以自定义方法,但注意不要和系统默认提供的五个方法名重复,这样不会报错,但方法名如果重复的时候,系统会优先使用我们自定义的方法,而系统提供的被重复的方法则会被覆盖,不会执行
在视图集中,程序员可以通过action对象属性来回去当前请求视图集时的动作是哪个 - 例如:
def get_serializer_class(self):
if self.action == 'create':
return OrderCommitSerializer
else:
return OrderDataSerializer
常用的是视图集的父类
1、ViewSet
- 继承自APIView,作用也和APIView基本类似,提供了身份认证,权限校验,流量管理等等,
- 在该视图集中,没有提供任何动作的动作方法,需要我们自己去实现行动方法
2、GenericViewSet
- 继承自GenericAPIView,作用也和GenericAPIView类似,提供了get_object,get_queryset等方法便于列表视图与详情信息视图的开发。但在实际开发中,使用较少或不用。
3、ModelViewSet
- 继承自GenericAPIView,同时包括了ListModelMixin,RetrieveModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin这五个扩展类
4、ReadOnlyModelViewSet
- 继承自GenericAPIView,同时包括了ListModelMixin,ResrieveModelMixin.
视图集中定义附加动作action
- 在视图集中,除了上述默认的方法动作外,还可以添加自定义的动作。
- 自定义动作需要使用rest_framework.decorators.action这个装饰器
from rest_framework.decorators import action
action装饰器可以接收两个参数
- methods:该动作支持的请求方式,列表传递
- detail: 表示是action中要处理的是否是视图资源的对象(即是否是通过url路径获取主键)
- - True表示使用通过URL中获取主键得到与之对应的数据对象
- - False表示不使用URL获取主键
# detail为Flase,表示不需要处理具体的模型类对象
# detail为True,表示要处理与pk(主键)对应的模型类对象
@action(methods=['get'],detail=True)
定义URL:
urlpattern = [ r’路由正则’,views.类名+as_view({‘请求方式’ : ‘方法名’})]
urlpatterns = [
url(r'^guns/$', views.GunsInfoViewSet.as_view({'get': 'list'})),
url(r'^guns/latest/$', views.GunsInfoViewSet.as_view({'get': 'latest'})),
url(r'^guns/(?P<pk>\d+)/$', views.GunsInfoViewSet.as_view({'get': 'retrieve'})),
url(r'^Guns/(?P<pk>\d+)/kills/$', views.GunsInfoViewSet.as_view({'put': 'kills'})),
]