视图总览
通用视图的继承关系
通用视图的继承关系_含方法和属性
视图这一部分得关系这两张图结合一些说明代码基本能表达的很清楚
1. 两个基类
1)APIView
rest_framework.views.APIView APIView是REST framework提供的所有视图的基类,继承自Django的View父类。
APIView与View的不同之处在于:
* 传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
* 视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
* 任何APIException异常都会被捕获到,并且处理成合适的响应信息;
* 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。
支持定义的属性:
* authentication_classes 列表或元祖,身份认证类
* permissoin_classes 列表或元祖,权限检查类
* throttle_classes 列表或元祖,流量控制类
在APIView中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法。
举例:
from rest_framework.views import APIView
from rest_framework.response import Response
# url(r'^books/$', views.BookListView.as_view()),
class BookListView(APIView):
'''使用APIView实现获取所有图书的接口'''
def get(self, request):
# 1.获取查询集
qs = BookInfo.objects.all()
# 2.创建序列化器
s = BookInfoSerializer(qs, many=True)
# 响应
return Response(s.data, status=status.HTTP_200_OK)
2)GenericAPIView
rest_framework.generics.GenericAPIView 继承自APIVIew,主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持。通常在使用时,可搭配一个或多个Mixin扩展类。
提供的关于序列化器使用的属性与方法
* 属性: * serializer_class 指明视图使用的序列化器
方法:
* get_serializer_class(self) 返回序列化器类,默认返回serializer_class,可以重写
* get_serializer(self, args, *kwargs) 返回序列化器对象,主要用来提供给Mixin扩展类使用,如果我们在视图中想要获取序列化器对象,也可以直接调用此方法。
注意,该方法在提供序列化器对象的时候,会向序列化器对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。
* request 当前视图的请求对象 * view 当前请求的类视图对象 * format 当前请求期望返回的数据格式
提供的关于数据库查询的属性与方法
* 属性: * queryset 指明使用的数据查询集
* 方法: * get_queryset(self) 返回视图使用的查询集,主要用来提供给Mixin扩展类使用,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以重写
* get_object(self) 返回详情视图所需的模型类数据对象,主要用来提供给Mixin扩展类使用。在试图中可以调用该方法获取详情信息的模型类对象。若详情访问的模型类对象不存在,会返回404。
该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。
举例:
from rest_framework.generics import GenericAPIView
class BookListView(GenericAPIView):
# 指定序列化器和数据库
serializer_class = BookInfoSerializer
queryset = BookInfo.objects.all()
def get(self, request):
qs = self.get_queryset()
ss = self.get_serializer(qs, many=True)
return Response(ss.data)
# 以下为针对单一查询的get方法(与上面的get看需求而定使用哪一种)
def get(self, request, pk):
# 获取单一对象
book = self.get_object()
# 初始化序列器
s = self.get_serializer(book)
return Response(s.data, status=status.HTTP_200_OK)
2. 五个扩展类
作用:
提供了几种后端视图(对数据资源进行增删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。这五个扩展类需要搭配GenericAPIView父类,因为五个扩展类的实现需要调用GenericAPIView提供的序列化器与数据库查询的方法。
1)ListModelMixin 列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。该Mixin的list方法会对数据进行过滤和分页。(源码可在使用中自行查看,此处省略)
from rest_framework.mixins import ListModelMixin
class BookListViewMi(mixins.ListModelMixin, GenericAPIView):
'''使用mixins.ListModelMixin + GenericAPIView实现获取所有图书的接口'''
# 指定序列化器和查询集
serializer_class = BookInfoSerializer
queryset = BookInfo.objects.all()
def get(self, request):
return self.list(request)
2)CreateModelMixin 创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。如果序列化器对前端发送的数据验证失败,返回400错误。
3) RetrieveModelMixin 详情视图扩展类,提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。如果存在,返回200, 否则返回404。
4)UpdateModelMixin 更新视图扩展类,提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。
5)DestroyModelMixin 删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。成功返回204,不存在返回404。
后四种应用于第一种很类似,具体使用只是函数的请求类型不一样,get、post、put、delete,只有delete、put(self, request, pk),多个pk
3. 几个可用子类视图
1) CreateAPIView
提供 post 方法 继承自: GenericAPIView、CreateModelMixin
2)ListAPIView
提供 get 方法 继承自:GenericAPIView、ListModelMixin
3)RetrieveAPIView
提供 get 方法 继承自: GenericAPIView、RetrieveModelMixin
4)DestoryAPIView
提供 delete 方法 继承自:GenericAPIView、DestoryModelMixin
5)UpdateAPIView
提供 put 和 patch 方法 继承自:GenericAPIView、UpdateModelMixin
6)RetrieveUpdateAPIView
提供 get、put、patch方法 继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin
7)RetrieveUpdateDestoryAPIView
提供 get、put、patch、delete方法 继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin
4.视图集
4.1 常用视图集父类
1) ViewSet
继承自APIView与ViewSetMixin,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{'get':'list'})的映射处理工作。在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。
使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:
* list() 提供一组数据 * retrieve() 提供单个数据 * create() 创建数据 * update() 保存数据 * destory() 删除数据
ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上。
from rest_framework.viewsets import ViewSet
class BookInfoView_Set(ViewSet):
'''使用ViewSet实现:返回数据列表和单一数据'''
# 返回列表数据
def list(self, request):
qs = BookInfo.objects.all()
s = BookInfoSerializer(qs, many=True)
return Response(s.data)
# 返回单一数据
def retrieve(self, request, pk):
book = BookInfo.objects.get(id=pk)
s = BookInfoSerializer(book)
return Response(s.data)
在设置路由时,我们可以如下操作
urlpatterns = [
url(r'^books/$',BookInfoView_Set.as_view({'get':'list'}),
url(r'^books/(?P<pk>\d+)/$',BookInfoView_Set.as_view({'get': 'retrieve'})
]
2)GenericViewSet
使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView,所以还需要继承GenericAPIView。GenericViewSet就帮助我们完成了这样的继承工作,继承自GenericAPIView与ViewSetMixin,在实现了调用as_view()时传入字典(如{'get':'list'})的映射处理工作的同时,还提供了GenericAPIView提供的基础方法,可以直接搭配Mixin扩展类使用
from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action
class BookInfoView_Gn(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
'''使用mixins + GenericViewSet实现获取所有图书和单一图书的接口'''
# 指定序列化器和查询集
serializer_class = BookInfoSerializer
queryset = BookInfo.objects.all()
url的定义
urlpatterns = [
url(r'^books/$', views.BookInfoView_Gn.as_view({'get': 'list'})),
url(r'^books/(?P<pk>\d+)/$', views.BookInfoView_Gn.as_view({'get': 'retrieve'})),
]
3)ReadOnlyModelViewSet
继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin
from rest_framework.viewsets import ReadOnlyModelViewSet
class BookInfoView_Ro(ReadOnlyModelViewSet):
'''使用mixins + GenericViewSet实现获取所有图书和单一图书的接口'''
# 指定序列化器和查询集
serializer_class = BookInfoSerializer
queryset = BookInfo.objects.all()
4)ModelViewSet
继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
class BookInfoViewSet(ModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
ModelViewSet源码:(功能最强大的视图集)
class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
"""
A viewset that provides default `create()`, `retrieve()`, `update()`,
`partial_update()`, `destroy()` and `list()` actions.
"""
pass
4.2 视图集中定义附加action动作
在视图集中,除了上述默认的方法动作外,还可以添加自定义动作。
class CustomizeAction(ReadOnlyModelViewSet):
'''
list:
返回图书列表数据
retrieve:
返回图书详情数据
latest:
返回最新的图书数据
update_bread:
修改图书的阅读量
'''
# 指定序列化器和查询集
serializer_class = BookInfoSerializer
queryset = BookInfo.objects.all()
# 自定义行为: 获取倒序后的最新书籍信息
@action(methods=['GET'], detail=False) # 在urls中如果用Routers 定义url需要加上action装饰器,如果是普通url定义不需要加
def latest(self, request):
book = BookInfo.objects.latest('id')
s = self.get_serializer(book)
return Response(s.data)
# 自定义行为: 修改书籍阅读量
@action(methods=['PUT'], detail=True) # 在urls中如果用Routers 定义url需要加上action装饰器,如果是普通url定义不需要加
def update_bread(self, request, pk):
book = BookInfo.objects.get(id=pk)
book.bread = request.data.get('bread')
book.save()
s = self.get_serializer(book)
return Response(s.data)
url的定义
urlpatterns = [
url(r'^books/$', views.CustomizeAction.as_view({'get': 'list'})),
url(r'^books/latest/$', views.CustomizeAction.as_view({'get': 'latest'})),
url(r'^books/(?P<pk>\d+)/$', views.CustomizeAction.as_view({'get': 'retrieve'})),
url(r'^books/(?P<pk>\d+)/read/$', views.CustomizeAction.as_view({'put': 'read'})),
]
Routers url的定义
router = DefaultRouter()
router.register('books/action', views.CustomizeAction)
urlpatterns += router.urls