关于Rest Framework中View、APIView与GenericAPIView的对比分析

 https://blog.csdn.net/odyssues_lee/article/details/80895207
https://blog.csdn.net/odyssues_lee?t=1

1)APIView(rest_framework.views.APIView)

APIView是REST framework提供的所有视图的基类,继承自Django的View父类。

APIViewView的不同之处在于:

  • 传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
  • 视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
  • 任何APIException异常都会被捕获到,并且处理成合适的响应信息;
  • 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制
支持定义的属性:
  • authentication_classes 列表或元祖,身份认证类
  • permissoin_classes 列表或元祖,权限检查类
  • throttle_classes 列表或元祖,流量控制类

2)GenericAPIView(rest_framework.generics.GenericAPIView)

继承自APIVIew增加了对于列表视图和详情视图可能用到的通用支持方法。通常使用时,可搭配一个或多个Mixin扩展类。

支持定义的属性:
  • 列表视图与详情视图通用:

    • queryset 列表视图的查询集
    • serializer_class 视图使用的序列化器
  • 列表视图使用:
    • pagination_class 分页控制类
    • filter_backends 过滤控制后端
  • 详情页视图使用:
    • lookup_field 查询单一数据库对象时使用的条件字段,默认为'pk'
    • lookup_url_kwarg 查询单一数据时URL中的参数关键字名称,默认与look_field相同
提供的方法:
  • 列表视图与详情视图通用:

    • get_queryset(self)

      返回视图使用的查询集,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以重写,例如:

      1.  
        defget_queryset(self):
      2.  
        user = self.request.user
      3.  
        return user.accounts.all()
    • get_serializer_class(self)

      返回序列化器类,默认返回serializer_class,可以重写,例如:

      1.  
        defget_serializer_class(self):
      2.  
        if self.request.user.is_staff:
      3.  
        return FullAccountSerializer
      4.  
        return BasicAccountSerializer
    • get_serializer(self, args, *kwargs)

      返回序列化器对象,被其他视图或扩展类使用,如果我们在视图中想要获取序列化器对象,可以直接调用此方法。

      注意,在提供序列化器对象的时候,REST framework会向对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。

  • 详情视图使用:

    • get_object(self) 返回详情视图所需的模型类数据对象,默认使用lookup_field参数来过滤queryset。 在试图中可以调用该方法获取详情信息的模型类对象。

      若详情访问的模型类对象不存在,会返回404。

      该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。

举例:

  1.  
    # url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view()),
  2.  
    classBookDetailView(GenericAPIView):
  3.  
    queryset = BookInfo.objects.all()
  4.  
    serializer_class = BookInfoSerializer
  5.  
     
  6.  
    defget(self, request, pk):
  7.  
    book = self.get_object()
  8.  
    serializer = self.get_serializer(book)
  9.  
    return Response(serializer.data)

!!!!五个扩展类!!!!

1)ListModelMixin

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

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

源代码:

  1.  
    classListModelMixin(object):
  2.  
    """
  3.  
    List a queryset.
  4.  
    """
  5.  
    deflist(self, request, *args, **kwargs):
  6.  
    # 过滤
  7.  
    queryset = self.filter_queryset(self.get_queryset())
  8.  
    # 分页
  9.  
    page = self.paginate_queryset(queryset)
  10.  
    if page is not None:
  11.  
    serializer = self.get_serializer(page, many=True)
  12.  
    return self.get_paginated_response(serializer.data)
  13.  
    # 序列化
  14.  
    serializer = self.get_serializer(queryset, many=True)
  15.  
    return Response(serializer.data)

举例:

  1.  
    from rest_framework.mixins import ListModelMixin
  2.  
     
  3.  
    classBookListView(ListModelMixin, GenericAPIView):
  4.  
    queryset = BookInfo.objects.all()
  5.  
    serializer_class = BookInfoSerializer
  6.  
     
  7.  
    defget(self, request):
  8.  
    return self.list(request)

2)CreateModelMixin

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

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

源代码:

  1.  
    classCreateModelMixin(object):
  2.  
    """
  3.  
    Create a model instance.
  4.  
    """
  5.  
    defcreate(self, request, *args, **kwargs):
  6.  
    # 获取序列化器
  7.  
    serializer = self.get_serializer(data=request.data)
  8.  
    # 验证
  9.  
    serializer.is_valid(raise_exception=True)
  10.  
    # 保存
  11.  
    self.perform_create(serializer)
  12.  
    headers = self.get_success_headers(serializer.data)
  13.  
    return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
  14.  
     
  15.  
    defperform_create(self, serializer):
  16.  
    serializer.save()
  17.  
     
  18.  
    defget_success_headers(self, data):
  19.  
    try:
  20.  
    return {'Location': str(data[api_settings.URL_FIELD_NAME])}
  21.  
    except (TypeError, KeyError):
  22.  
    return {}

3) RetrieveModelMixin

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

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

源代码:

  1.  
    classRetrieveModelMixin(object):
  2.  
    """
  3.  
    Retrieve a model instance.
  4.  
    """
  5.  
    defretrieve(self, request, *args, **kwargs):
  6.  
    # 获取对象,会检查对象的权限
  7.  
    instance = self.get_object()
  8.  
    # 序列化
  9.  
    serializer = self.get_serializer(instance)
  10.  
    return Response(serializer.data)

举例:

  1.  
    classBookDetailView(RetrieveModelMixin, GenericAPIView):
  2.  
    queryset = BookInfo.objects.all()
  3.  
    serializer_class = BookInfoSerializer
  4.  
     
  5.  
    defget(self, request, pk):
  6.  
    return self.retrieve(request)

4)UpdateModelMixin

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

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

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

源代码:

  1.  
    classUpdateModelMixin(object):
  2.  
    """
  3.  
    Update a model instance.
  4.  
    """
  5.  
    defupdate(self, request, *args, **kwargs):
  6.  
    partial = kwargs.pop('partial', False)
  7.  
    instance = self.get_object()
  8.  
    serializer = self.get_serializer(instance, data=request.data, partial=partial)
  9.  
    serializer.is_valid(raise_exception=True)
  10.  
    self.perform_update(serializer)
  11.  
     
  12.  
    if getattr(instance, '_prefetched_objects_cache', None):
  13.  
    # If 'prefetch_related' has been applied to a queryset, we need to
  14.  
    # forcibly invalidate the prefetch cache on the instance.
  15.  
    instance._prefetched_objects_cache = {}
  16.  
     
  17.  
    return Response(serializer.data)
  18.  
     
  19.  
    defperform_update(self, serializer):
  20.  
    serializer.save()
  21.  
     
  22.  
    defpartial_update(self, request, *args, **kwargs):
  23.  
    kwargs['partial'] = True
  24.  
    return self.update(request, *args, **kwargs)

5)DestroyModelMixin

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

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

源代码:

  1.  
    classDestroyModelMixin(object):
  2.  
    """
  3.  
    Destroy a model instance.
  4.  
    """
  5.  
    defdestroy(self, request, *args, **kwargs):
  6.  
    instance = self.get_object()
  7.  
    self.perform_destroy(instance)
  8.  
    return Response(status=status.HTTP_204_NO_CONTENT)
  9.  
     
  10.  
    defperform_destroy(self, instance):
  11.  
    instance.delete()

3. 几个可用子类视图

1) CreateAPIView

提供 post 方法

继承自: GenericAPIView、CreateModelMixin

2)ListAPIView

提供 get 方法

继承自:GenericAPIView、ListModelMixin

3)RetireveAPIView

提供 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

视图集ViewSet

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

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

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

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

  1.  
    classBookInfoViewSet(viewsets.ViewSet):
  2.  
     
  3.  
    deflist(self, request):
  4.  
    ...
  5.  
     
  6.  
    defretrieve(self, request, pk=None):
  7.  
    ...

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

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

action属性

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

例如:

  1.  
    defget_serializer_class(self):
  2.  
    if self.action == 'create':
  3.  
    return OrderCommitSerializer
  4.  
    else:
  5.  
    return OrderDataSerializer

常用视图集父类

1) ViewSet

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

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

2)GenericViewSet

继承自GenericAPIView,作用也与GenericAPIVIew类似,提供了get_object、get_queryset等方法便于列表视图与详情信息视图的开发。

3)ModelViewSet

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

4)ReadOnlyModelViewSet

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

视图集中定义附加action动作

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

添加自定义动作需要使用rest_framework.decorators.action装饰器。

以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。

action装饰器可以接收两个参数:

  • methods: 该action支持的请求方式,列表传递
  • detail: 表示是action中要处理的是否是视图资源的对象(即是否通过url路径获取主键)
    • True 表示使用通过URL获取的主键对应的数据对象
    • False 表示不使用URL获取主键

举例:

  1.  
    from rest_framework import mixins
  2.  
    from rest_framework.viewsets import GenericViewSet
  3.  
    from rest_framework.decorators import action
  4.  
     
  5.  
    classBookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
  6.  
    queryset = BookInfo.objects.all()
  7.  
    serializer_class = BookInfoSerializer
  8.  
     
  9.  
    # detail为False 表示不需要处理具体的BookInfo对象
  10.  
    @action(methods=['get'], detail=False)
  11.  
    deflatest(self, request):
  12.  
    """
  13.  
    返回最新的图书信息
  14.  
    """
  15.  
    book = BookInfo.objects.latest('id')
  16.  
    serializer = self.get_serializer(book)
  17.  
    return Response(serializer.data)
  18.  
     
  19.  
    # detail为True,表示要处理具体与pk主键对应的BookInfo对象
  20.  
    @action(methods=['put'], detail=True)
  21.  
    defread(self, request, pk):
  22.  
    """
  23.  
    修改图书的阅读量数据
  24.  
    """
  25.  
    book = self.get_object()
  26.  
    book.bread = request.data.get('read')
  27.  
    book.save()
  28.  
    serializer = self.get_serializer(book)
  29.  
    return Response(serializer.data)

url的定义

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

关于Rest Framework中View、APIView与GenericAPIView的对比分析的更多相关文章

  1. javascript中call,apply,bind的用法对比分析

    这篇文章主要给大家对比分析了javascript中call,apply,bind三个函数的用法,非常的详细,这里推荐给小伙伴们.   关于call,apply,bind这三个函数的用法,是学习java ...

  2. DRF中的APIView、GenericAPIView、ViewSet

    1.APIView(rest_framework.views import APIView),是REST framework提供的所有视图的基类,继承自Django的View. 传入到视图方法中的是R ...

  3. Java中的NIO和IO的对比分析

    总的来说,java中的IO和NIO主要有三点区别: IO NIO 面向流 面向缓冲 阻塞IO 非阻塞IO 无 选择器(Selectors) 1.面向流与面向缓冲 Java NIO和IO之间第一个最大的 ...

  4. php中数据库连接方式pdo和mysqli对比分析

    1)总的比较   PDO MySQLi 数据库支持 12种不同的数据库支持 支持MySQL API OOP OOP + 过程 Connection Easy Easy 命名参数 支持 不支持 对象映射 ...

  5. DRF的APIView、GenericAPIView、GenericViewSet的原理分析

    一.层次结构 GenericViewSet(ViewSetMixin, generics.GenericAPIView) ---DRF GenericAPIView(views.APIView) -- ...

  6. Django REST framework中的版本控制

    1.REST framework版本控制的流程分析 1.1 determine_version方法的执行流程 首先,请求到达REST framework的CBV,执行CBV中的dispatch方法再次 ...

  7. python3-开发进阶 django-rest framework 中的 版本操作(看源码解说)

    今天我们来说一说rest framework 中的 版本 操作的详解 首先我们先回顾一下 rest framework的流程: 请求进来走view ,然后view调用视图的dispath函数 为了演示 ...

  8. Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->Spring Framework中的spring web MVC模块

    spring framework中的spring web MVC模块 1.概述 spring web mvc是spring框架中的一个模块 spring web mvc实现了web的MVC架构模式,可 ...

  9. Android中View的绘制过程 onMeasure方法简述 附有自定义View例子

    Android中View的绘制过程 onMeasure方法简述 附有自定义View例子 Android中View的绘制过程 当Activity获得焦点时,它将被要求绘制自己的布局,Android fr ...

随机推荐

  1. envoy  功能介绍

    L3/L4 filter architecture: At its core, Envoy is an L3/L4 network proxy. A pluggable filter chain me ...

  2. ORA-28595: Extproc 代理: DLL 路径无效解决办法

    报错信息: ORA-28595: Extproc 代理: DLL 路径无效 ORA-06512: 在 "SDE.ST_GEOMETRY_SHAPELIB_PKG", line 70 ...

  3. python3 安装 past 包

    python3 安装 past 包 $ pip install future 错误现象 缺乏包的引用 from past.types import unicode 参考链接 https://pypi. ...

  4. 开学初的c

    cout<<a[i]<<" " 这个是先输出a[i]再输出空格 cout<<endl      这个是直接换行cout<<a[i]& ...

  5. SERDES高速系统(二)

    抖动.容忍度与功耗 前面我提到SERDES的最终性能要用传输速率和传输距离考核.使用眼图可以形象化地衡量SERDES的收发性能,但是更为精确的参数化衡量手段是抖动(Jitter).容忍度(Tolera ...

  6. PCIE接口的说明

    https://blog.csdn.net/u013253075/article/details/80835489

  7. Oracle 利用执行计划来避免排序操作

    在oracle中,利用index来避免排序 SQL) NOT NULL); SQL> CREATE INDEX IND_T_NOSORT_NAME ON T_NOSORT(NAME); SQL& ...

  8. Python Twisted系列教程10:增强defer功能的客户端

    作者:dave@http://krondo.com/an-introduction-to-asynchronous-programming-and-twisted/ 译者:杨晓伟(采用意译) 可以从这 ...

  9. 第十三章 MySQL用户管理(待续)

    ·············

  10. Python3.x 常用的新特性

    Python3.x 常用的新特性 print() 是函数,不是一个语句 raw_input()输入函数,改为 input() Python 3 对文本和二进制数据做了更为清晰的区分. 文本由unico ...