关于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. tensorflow dropout

    我们都知道dropout对于防止过拟合效果不错dropout一般用在全连接的部分,卷积部分不会用到dropout,输出曾也不会使用dropout,适用范围[输入,输出)1.tf.nn.dropout( ...

  2. (装)Android杂谈--禁止TimePicker控件通过keyboard输入

    Android 4.1版本以上用的是类似与ios的滚动时间控件,但是4.1以下,用的TimePicker确实通过点击上下按钮来更改时间的,虽然也提供了编辑框编辑,但是可能会超出编辑范围 如果要禁止编辑 ...

  3. Java 成员方法的定义

    方法的定义: 方法是类或对象的行为特征的抽象. Java中的方法不能独立存在,所有的方法必须定义在类中. 使用 “类名.方法” 或 “对象.方法” 的形式调用. 语法格式: 权限修饰符 返回值类型 方 ...

  4. EXCEL类型库的添加

    1. 创建新的C++工程 创建基于对话框的MFC程序 2. 添加库.添加Excel类库 在工程名上右键,选择“添加”—“类”(或者点击菜单栏的“项目”->“添加类”),选择“TypeLib中的M ...

  5. FPGA前世今生(一)

    关于FPGA,我想做硬件的或多或少都听过.从上世纪80年代算来,FPGA已走过了30多个年头.我们以FPGA两大生产厂商,两大巨头之一的INTEL(altera)公司的FPGA为例,为大家逐步介绍FP ...

  6. selenium 定位元素可以用多个findElement

    selenium 定位元素可以用多个findElement,如driver.findElement(By.id"XXX").findElement(By.linkText(XXX) ...

  7. Effective java笔记2--创建于销毁对象

    一.创建对象的两种方式 1.提供公有的构造器. 2.提供一个返回类实例的静态方法. 二.使用静态方法创建对象 优势: 1.静态工厂方法的一个好处是,与构造函数不同,静态工厂方法具有名字.产生的客户端代 ...

  8. HUSTOJ 昆虫繁殖(递推)

    昆虫繁殖 时间限制: 1 Sec  内存限制: 128 MB提交: 25  解决: 16[提交][状态][讨论版][命题人:quanxing] 题目描述 科学家在热带森林中发现了一种特殊的昆虫,这种昆 ...

  9. nandflash裸机程序分析

    它包含7个文件: head.S init.c main.c Makefile nand.c nand.lds 我们之前的程序都是在nandflash的前4k放代码,上电后自动拷贝到SRAM中,之后将S ...

  10. List去重与排序

    最简单的方法:利用Where一句话去重 pointLst = pointLst.Where((x, i) => pointLst.FindIndex(z => z.POINT_ID == ...