drf之视图类
1.两个基类
(1)APIView
rest_framework.views.APIView
APIView是REST framework提供的所有视图的基类,是Django的View类的子类。
drf中的APIView和Django中的View的不同:
传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
任何APIException异常都会被捕获到,并且处理成合适的响应信息;
在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。
支持定义的属性:
authentication_classes 列表或元祖,身份认证类
permissoin_classes 列表或元祖,权限检查类
throttle_classes 列表或元祖,流量控制类
在APIView中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法。
(2)GenericAPIView:通用视图类
rest_framework.generics.GenericAPIView
是APIView类的子类。相比增加了操作序列化器和数据库查询的方法。增加了对列表视图和详情视图可能用到的通用支持方法。通常和一个或者多个mixin扩展类搭配使用
支持定义的属性:
列表视图和详情视图通用:
queryset:视图的查询集
serializer_class:视图使用的序列化器
列表视图使用:
pagination_class:分页控制类
filter_backends: 过滤控制后端
详情视图使用:
lookup_field:查询单一数据库对象时使用的条件查询,默认为”pk”。
lookup_url_kwarg:查询单一数据时URL中的参数关键字名称,默认与lookup_field相同
提供的方法:
列表视图和详情视图通用:
get_queryset(self):返回视图使用的查询集。是视图获取数据的基础。默认返回queryset属性。可以重写自定义。
get_serializer_class(self):返回序列化器类,默认返回serializer_class属性,也可以重写。
get_serializer(self, *args, **kwargs):返回序列化器对象,被其他视图或者扩展类使用。如果想在视图中获取序列化对象,可以通过此方法得到。
详情视图使用的方法:
get_object(self):返回详情页视图所需的模型类数据对象。默认使用lookup_file属性来过滤queryset对象。在视图类中调用此方法可以获得详情信息的模型类对象。
例子:
get_querset(self) def get_querset(self): user = self.reques.user return user.account.all() get_serializer_class(self) def get_serializer_class(self): if self.request.user.is_staff: return FullAccountSerializer return BasicAccountSerializer #url(r’^book/(?P<pk>\d+)/$’, views.BookDetailView.as_view()), class BookDetailView(GenericAPIView): queryset = BookInfo.objects.all() #指定查询集 serializer_class = BookInfoSerializer #指定序列化器 def get(self, request, pk): book = self.get_object() #获取查询集(pk就是get_object。多个就是queryset) serializer = self.get_serializer(book) #创建序列化器对象 return Response(serializer.data)
GenericAPIView的这些方法,要配合扩展类mixin使用,就大大优化了。
2. 5个扩展类mixin
5个扩展类分别是:
ListModelMixin:提供list方法快速实现列表视图。
CreateModelMixin:提供create方法快速实现创建资源视图
RetrieveModelMixin:提供retrieve方法,快速返回一个存在的数据对象(需传入pk)
UpdateModelMixin:update方法,更新一个存在的数据对象。partial_update,局部更新。
DestoryModelMixin:提供destory方法,快速删除一个已经存在的对象。
(1)ListModelMixin:列表视图扩展类
功能:快速实现列表视图、对数据进行过滤和分类。成功返回200状态码
源代码:
class ListModelMixin(object): def list(self, request, *args, **kwargs): #过滤 queryset = self.filter_queryset(self.get_queryset()) #分页 page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) #序列化 serializer = self.get_serializer(queryset, many=true) return Response(serializer.data)
例子:
from rest_framework.mixins import ListModelMixin class BookListView(ListModelMixin, GenericAPIView): queryset = BookInfo.objects.all() serializer_class = BookInfoSerializer def get(self, request): return self.list(request)
父类帮我们把return之前的事情都做了,只需调用方法,传入参数就行。
(2)CreateModelMixin:创建视图扩展类
提供create(request, *args, **kwargs),实现快速创建资源的视图,成功返回201状态码。
(3)RetrieveModelMixin:详情视图扩展类
提供retrieve(request, *args, **kwargs),快速返回一个存在的数据对象。如果存在,返回200。
例子:
class BookDetailView(RetrieveModelMixin, GenericAPIView): queryset = BookInfo.objects.all() serializer_class = BookInfoSerializer def get(self, request, pk): retunrn self.retrieve(request)
(4)UpdateModelMixin:更新视图扩展类
(5)DestoryModelMixin:删除视图扩展类
注意:上面的扩展类都和GenericAPIView搭配使用。不然谁给它那些类属性。
上面还能再简化。APIView
(1)CreateAPIView:提供post方法,相当于GenericAPIView+CreateModelMixin,也继承了二者 (2)ListAPIView:提供get方法。继承自GenericAPIView、ListModelMixin (3)RetrieveAPIView:提供get方法。继承GenericAPIView、RetrieveModelMixin (4)DestoryAPIView:提供delete方法 (5)UpdateAPIView:提供put和patch方法 (6)RetrieveUpdateAPIView:提供get、put和patch方法。继承三者 (7)RetrieveUpdateDestoryAPIView:提供get、put、patch、delete方法。继承4者 所以,代码中的mixins.RetrieveModelMixin, GenericAPIView可以写成RetrieveAPIView
3.视图集
(1)ViewSet
前面的父类仍需写很多函数。ViewSet将几个操作放到一起(前面都是分开实现的)
list() :提供一组数据
retrieve():提供单个数据
create():创建数据
update():更新数据
destory():删除数据
ViewSet主要通过继承ViewSetMixin来实现在调用as_views()时传入字典(如{“get”:”list”})的映射。
在ViewSet中,没有提供任何动作acton方法,需要我们自己实习那action方法。
ViewSet视图集类不再实现get()、post()方法,而是实现动作list()、create()等方法。
例子:
#视图中 class BookInfoViewSet(viewsets.ViewSet): def list(self, request): books = BookInfo.all() serializer = BookInfoSerializer(books, many=True) return Response(serializer.data) def retrieve(self, request, pk=None): try: books = BookInfo.objects.get(id=pk) except BookInfo.DoesNotExist: return Response(status=status.HTTP_$)$_NOT_FOUND) serializer = BookInfoSerializer(books) return Response(serializer.data) #urls.py中 url(r’^books/$’, BookInfoViewSet.as_view({“get”:”list”})), url(r’^books/(?P<pk>\d+)/$’, BookInfoViewSet.as_view({“get”:”retrieve”})), 视图集只在使用as_view()方法时,才会将action动作与具体的请求方法对应上。
(2)GenericViewSet
使用ViewSet并不方便,需要自己写list、update等方法。而这些方法与Mixin扩展类提供的方法同名,可以通过继承Mixin扩展类来复用这些方法,不用自己编写。但Mixin扩展类依赖于GenericAPIView,所以还要继承GenericAPIView.
GenericViewSet就包括了GenericAPIView和ViewSet,然后再加上不同的扩展类,就复用了扩展类的方法。
例子:
class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet): queryset = BookInfo.objects.all() serializer_class = BookInfoSerializer #设置url urls.py中 url(r’^books/$’, BookInfoViewSet.as_view({“get”:”list”})), url(r’^books/(?P<pk>\d+)/$’, BookInfoViewSet.as_view({“get”:”retrieve”})),
(3)ModelViewSet
ModelViewset继承了GenericViewSet,同时包括所有的5大扩展类。
例子:
class BookInfoViewSet(ModelViewSet): queryset = BookInfo.objects.all() serializer_class = BookInfoAllSeirializer
如果没有写方法,那么在urls中要以router的方式配置注册路由。
需要什么方法,在url中配置什么字典就行。
(4)ReadOnlyModelViewset
继承自GenericViewSet,同时也包括ListModelMixin和RetrieveModelMixin。只查
例子:
class BookInfoViewSet(ReadOnlyModelViewSet): #使用视图集返回列表和单一数据 serializer_class = BookInfoSerializer queryset = BookInfo.objects.all() @action(method=[‘get’], detail=False) def latest(self, request): book = BookInfo.objects.latest(‘id’) #取id最后一个 serializer = self.get_serializer(book) return Response(serializer.data)
action装饰器,给自定义的方法生成url地址,不需要在路由中设置。 两个参数: methods:声明action对应的请求方式,列表传递。 detail:声明该action的路径时要不要加主键pk。 True此时路径为xxx/<pk>/action方法名。 False此时路径为xxx/action方法名。