zoukankan      html  css  js  c++  java
  • DRF ---- 视图类 数据工具类 工具视图集 视图集

    from rest_framework.generics import GenericAPIView
    # 继承了APIview 拥有APIview所有
    	
    def filter_queryset(self, queryset): # 返回questset对象
       
    def get_object(self):
        
    def get_serializer(self, *args, **kwargs):    
        
    def get_queryset(self):
    

    一. 视图类

    1. ApiView

    from rest_framework.views import APIView
    
    class APIView(View): # 继承 django的 View
        pass
    

    APIViewREST framework提供的所有视图的基类,继承自DjangoView父类。

    主要干了 局部禁用csrf认证 二次封装response request 三大认证exception

    APIview详细源码

    2. GenericAPIView

    from rest_framework.generics import GenericAPIView
    
    class GenericAPIView(views.APIView): # 继承 APIview 所以拥有APIView的所有
        pass
    

    类中提供了很多帮助我们操作序列化时 使用的方法

    get_queryset 配置queryset

    class CarGenericAPIView(GenericAPIView):
        queryset = models.Car.objects.filter(is_delete=False).all()
    	# 在视图类中配置queryset
    

    源码导读:

    class GenericAPIView(views.APIView):
        # 初始化初始化queryset 默认为空
        # queryset 指明使用的数据查询集
        queryset = None
    
        def get_queryset(self):
    		# 断言 判断自己的queryset 是不是为空 然后抛异常
            assert self.queryset is not None, (.....)
            # 设置值
            queryset = self.queryset
            # 判断 queryset 是否是 QuerySet 的实例 
            if isinstance(queryset, QuerySet):
                # 如果是的话就帮你点 all
                queryset = queryset.all()
            # 最后返回 queryset
            return queryset
    
    # 不能直接写到objects结束,因为objects结束时,不是QuerySet对象,而是Manager对象,但 .all() 和 .filter() 后一定是QuerySet对象
    

    总结: 判断自己的queryset是否为空 判断是否是QuerySet对象后.all 最后得到的一定是 QuerySet

    get_object 配置 lookup_url_kwarg

    class CarGenericAPIView(GenericAPIView):
        lookup_url_kwarg = 'pk'
    	# 主键或者外键 配置 且路由的有名分组也要一样!
    

    url

    url(r'^v2/cars/(?P<pk>d+)/', views.xxx.as_view()) # 有名字分组 pk
    
    class GenericAPIView(views.APIView):
        # 设置值 且 lookup_url_kwarg为 none
        lookup_field = 'pk'
        lookup_url_kwarg = None
    
        def get_object(self):
    		# 调用了get_queryset()方法后继续调用 filter_queryset()
            queryset = self.filter_queryset(self.get_queryset())
    
            lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
    		# ......
    		# 中间我们也不管用了啥方法 但是最后返回的是obj
            return obj
    

    get_serializer 配置 serializer_class

    class CarGenericAPIView(GenericAPIView):
        queryset = models.Car.objects.filter(is_delete=False).all()
        serializer_class = serializers.CarModelSerializer # 配置自己的serializers
        lookup_url_kwarg = 'pk'
    

    源码:

      	serializer_class = None
        def get_serializer(self, *args, **kwargs):
            # 获取序列化类 
            serializer_class = self.get_serializer_class()
            # 多余的参数传入 这样你的 validata才可以获取到值
            kwargs['context'] = self.get_serializer_context()
            # 返回 serializer_class() 类初始化
            return serializer_class(*args, **kwargs)
    

    get_serializer_class

        def get_serializer_class(self):
            # 判断是否配置serializer_class
            assert self.serializer_class is not None, (...)
            # 返回序列化类
            return self.serializer_class
    

    GenericAPIView配置 结合使用:

    # url(r'^books/(?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() # get_object()方法根据pk参数查找queryset中的数据对象
            serializer = self.get_serializer(book)
            return Response(serializer.data)
    

    二.视图工具类

    from rest_framework import mixins
    

    五个视图扩展类

    作用:

    提供了几种后端视图(对数据资源进行曾删改查)处理流程的实现,如果需要编写的视图属于这五种,则

    视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。

    这五个扩展类需要搭配GenericAPIView父类,因为五个扩展类的实现需要调用GenericAPIView提供的

    序列化器与数据库查询的方法。

    1)ListModelMixin 群查

    列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。

    该Mixin的list方法会对数据进行过滤和分页

    源代码:

    class ListModelMixin(object):
        """
        List a queryset.
        """
        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)
    

    2)CreateModelMixin 单增

    创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。

    如果序列化器对前端发送的数据验证失败,返回400错误。

    源代码:

    class CreateModelMixin(object):
        """
        Create a model instance.
        """
        def create(self, request, *args, **kwargs):
            # 获取序列化器
            serializer = self.get_serializer(data=request.data)
            # 验证
            serializer.is_valid(raise_exception=True)
            # 保存
            self.perform_create(serializer)
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
    
        def perform_create(self, serializer):
            serializer.save()
    
        def get_success_headers(self, data):
            try:
                return {'Location': str(data[api_settings.URL_FIELD_NAME])}
            except (TypeError, KeyError):
                return {}
    

    3) RetrieveModelMixin 单查

    详情视图扩展类,提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。

    如果存在,返回200, 否则返回404。

    源代码:

    class RetrieveModelMixin(object):
        """
        Retrieve a model instance.
        """
        def retrieve(self, request, *args, **kwargs):
            # 获取对象,会检查对象的权限
            instance = self.get_object()
            # 序列化
            serializer = self.get_serializer(instance)
            return Response(serializer.data)
    

    举例:

    class BookDetailView(RetrieveModelMixin, GenericAPIView):
        queryset = BookInfo.objects.all()
        serializer_class = BookInfoSerializer
    
        def get(self, request, pk):
            return self.retrieve(request)
    

    4)UpdateModelMixin 单改

    更新视图扩展类,提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。

    同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。

    成功返回200,序列化器校验数据失败时,返回400错误。

    源代码:

    class UpdateModelMixin(object):
        """
        Update a model instance.
        """
        def update(self, request, *args, **kwargs):
            partial = kwargs.pop('partial', False)
            instance = self.get_object()
            serializer = self.get_serializer(instance, data=request.data, partial=partial)
            serializer.is_valid(raise_exception=True)
            self.perform_update(serializer)
    
            if getattr(instance, '_prefetched_objects_cache', None):
                # If 'prefetch_related' has been applied to a queryset, we need to
                # forcibly invalidate the prefetch cache on the instance.
                instance._prefetched_objects_cache = {}
    
            return Response(serializer.data)
    
        def perform_update(self, serializer):
            serializer.save()
    
        def partial_update(self, request, *args, **kwargs):
            kwargs['partial'] = True
            return self.update(request, *args, **kwargs)
    

    5)DestroyModelMixin 单删

    删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。

    成功返回204,不存在返回404。

    源代码:

    class DestroyModelMixin(object):
        """
        Destroy a model instance.
        """
        def destroy(self, request, *args, **kwargs):
            instance = self.get_object()
            self.perform_destroy(instance)
            return Response(status=status.HTTP_204_NO_CONTENT)
    
        def perform_destroy(self, instance):
            instance.delete()
    

    使用:

    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)
    

    三. 工具视图集 七个子类视图

    from rest_framework import generics
    

    1)CreateAPIView # 单增

    提供 post 方法

    继承自: GenericAPIView、CreateModelMixin

    2)ListAPIView

    提供 get 方法

    继承自:GenericAPIView、ListModelMixin

    class CreateAPIView(mixins.CreateModelMixin,
                        GenericAPIView):
    
        def post(self, request, *args, **kwargs):
            return self.create(request, *args, **kwargs)
    
    

    3)RetrieveAPIView # 单查

    提供 get 方法

    继承自: GenericAPIView、RetrieveModelMixin

    class RetrieveAPIView(mixins.RetrieveModelMixin,
                          GenericAPIView):
    
        def get(self, request, *args, **kwargs):
            return self.retrieve(request, *args, **kwargs)
    

    4)DestoryAPIView # 单删

    提供 delete 方法

    继承自:GenericAPIView、DestoryModelMixin

    class DestroyAPIView(mixins.DestroyModelMixin,
                         GenericAPIView):
     
        def delete(self, request, *args, **kwargs):
            return self.destroy(request, *args, **kwargs)
    

    5)UpdateAPIView # 单改

    提供 put 和 patch 方法

    继承自:GenericAPIView、UpdateModelMixin

    class UpdateAPIView(mixins.UpdateModelMixin,
                        GenericAPIView):
    
        def put(self, request, *args, **kwargs):
            return self.update(request, *args, **kwargs)
    
        def patch(self, request, *args, **kwargs):
            return self.partial_update(request, *args, **kwargs)
    

    6)RetrieveUpdateAPIView # 单查 单改

    提供 get、put、patch方法

    继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin

    class RetrieveUpdateAPIView(mixins.RetrieveModelMixin,
                                mixins.UpdateModelMixin,
                                GenericAPIView):
        def get(self, request, *args, **kwargs):
            return self.retrieve(request, *args, **kwargs)
    
        def put(self, request, *args, **kwargs):
            return self.update(request, *args, **kwargs)
    
        def patch(self, request, *args, **kwargs):
            return self.partial_update(request, *args, **kwargs)
    

    7)RetrieveUpdateDestoryAPIView # 单查 单改 单删

    提供 get、put、patch、delete方法

    继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin

    class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
                                       mixins.UpdateModelMixin,
                                       mixins.DestroyModelMixin,
                                       GenericAPIView):
    
        def get(self, request, *args, **kwargs):
            return self.retrieve(request, *args, **kwargs)
    
        def put(self, request, *args, **kwargs):
            return self.update(request, *args, **kwargs)
    
        def patch(self, request, *args, **kwargs):
            return self.partial_update(request, *args, **kwargs)
    
        def delete(self, request, *args, **kwargs):
            return self.destroy(request, *args, **kwargs)
    
    

    使用:

    # 单独完成群查接口
    from rest_framework.generics import ListAPIView
    class CarListAPIView(ListAPIView):
        queryset = models.Car.objects.filter(is_delete=False).all()
        serializer_class = serializers.CarModelSerializer
    
    # 单查(get)、单整体改(put)、单局部改(patch)、单删接口(delete)
    from rest_framework.generics import RetrieveUpdateDestroyAPIView
    class CarRetrieveUpdateDestroyAPIView(RetrieveUpdateDestroyAPIView):
        queryset = models.Car.objects.filter(is_delete=False).all()
        serializer_class = serializers.CarModelSerializer
    

    四.视图集ViewSet

    from rest_framework import viewsets
    

    使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:

    • list() 提供一组数据
    • retrieve() 提供单个数据
    • create() 创建数据
    • update() 保存数据
    • destory() 删除数据

    ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。

    视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上。如:

    class BookInfoViewSet(viewsets.ViewSet):
    
        def list(self, request):
            books = BookInfo.objects.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_404_NOT_FOUND)
            serializer = BookInfoSerializer(books)
            return Response(serializer.data)
    

    在设置路由时,我们可以如下操作

    urlpatterns = [
        url(r'^books/$', BookInfoViewSet.as_view({'get':'list'}),
        url(r'^books/(?P<pk>d+)/$', BookInfoViewSet.as_view({'get': 'retrieve'})
    ]
    

    常用视图集父类

    class ViewSet(ViewSetMixin, views.APIView):
        pass
    
    class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
        pass
    

    1) ViewSet

    继承自APIViewViewSetMixin,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。

    ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{'get':'list'})的映射处理工作。

    在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。

    2)GenericViewSet

    使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView,所以还需要继承GenericAPIView

    GenericViewSet就帮助我们完成了这样的继承工作,继承自GenericAPIViewViewSetMixin,在实现了调用as_view()时传入字典(如{'get':'list'})的映射处理工作的同时,还提供了GenericAPIView提供的基础方法,可以直接搭配Mixin扩展类使用。

    举例:

    from rest_framework import mixins
    from rest_framework.viewsets import GenericViewSet
    from rest_framework.decorators import action
    
    class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
        queryset = BookInfo.objects.all()
        serializer_class = BookInfoSerializer
    

    url的定义

    urlpatterns = [
        url(r'^books/$', views.BookInfoViewSet.as_view({'get': 'list'})),
        url(r'^books/(?P<pk>d+)/$', views.BookInfoViewSet.as_view({'get': 'retrieve'})),
    ]
    

    3)ModelViewSet

    继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

    4)ReadOnlyModelViewSet

    继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin。

    视图集中定义附加action动作

    在视图集中,除了上述默认的方法动作外,还可以添加自定义动作。

    举例:

    from rest_framework import mixins
    from rest_framework.viewsets import GenericViewSet
    from rest_framework.decorators import action
    
    class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
        queryset = BookInfo.objects.all()
        serializer_class = BookInfoSerializer
    
        def latest(self, request):
            """
            返回最新的图书信息
            """
            book = BookInfo.objects.latest('id')
            serializer = self.get_serializer(book)
            return Response(serializer.data)
    
        def read(self, request, pk):
            """
            修改图书的阅读量数据
            """
            book = self.get_object()
            book.bread = request.data.get('read')
            book.save()
            serializer = self.get_serializer(book)
            return Response(serializer.data)
    

    url的定义

    urlpatterns = [
        url(r'^books/$', views.BookInfoViewSet.as_view({'get': 'list'})),
        url(r'^books/latest/$', views.BookInfoViewSet.as_view({'get': 'latest'})),
        url(r'^books/(?P<pk>d+)/$', views.BookInfoViewSet.as_view({'get': 'retrieve'})),
        url(r'^books/(?P<pk>d+)/read/$', views.BookInfoViewSet.as_view({'put': 'read'})),
    ]
    

    action属性

    在视图集中,我们可以通过action对象属性来获取当前请求视图集时的action动作是哪个。

    例如:

    from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet
    from booktest.models import BookInfo
    from .serializers import BookInfoModelSerializer
    from rest_framework.response import Response
    class BookInfoModelViewSet(ModelViewSet):
        queryset = BookInfo.objects.all()
        serializer_class = BookInfoModelSerializer
    
        def get_top_5(self,request):
            """获取评论值最多的5条数据"""
            # 操作数据库
            print(self.action) # 获取本次请求的视图方法名
            
            
    通过路由访问到当前方法中.可以看到本次的action就是请求的方法名
    
  • 相关阅读:
    User Get 'Access Denied' with Excel Service WebPart
    How To Search and Restore files from Site Collection Recycle Bin
    How To Collect ULS Log from SharePoint Farm
    How To Restart timer service on all servers in farm
    How to Operate SharePoint User Alerts with PowerShell
    How to get Timer Job History
    Synchronization Service Manager
    SharePoint 2007 Full Text Searching PowerShell and CS file content with SharePoint Search
    0x80040E14 Caused by Max Url Length bug
    SharePoint 2007 User Re-created in AD with new SID issue on MySite
  • 原文地址:https://www.cnblogs.com/lddragon1/p/12121968.html
Copyright © 2011-2022 走看看