先看一张图,对DRF的各个APIView,Mixin,Viewset等有个基本印象:

具体使用方法:

1、APIView:

  DRF 的API视图 有两种实现方式:

  一种是基于函数的:@api_view

  一种是基于类的:APIView,APIView是Restframework提供的所有视图的基类,继承自Django的View父类

  1)@api_view

    使用@api_view装饰器,使得我们此处的Request不在是Django标准的HttpRequest,而是restframework的Request。

    默认情况下,只有GET请求会被接收,它也允许我们自己配置函数允许接收的请求类型

    @api_view():默认只接收GET请求

    @api_view(http_method_names=['GET']):指明接收的请求类型

    @api_view(['GET', 'POST']):接收get post请求

    @api_view(['GET','POST'])

    def Snippet_list(request):

      if request.method=="GET":

        pass

      elif request.method == "POST":

        pass

  2)APIView

    APIView是基于类的装饰器,显然,类视图更符合面向对象的原则,它支持GET POST PUT DELETE等请求类型,且各种类型的请求之间,有了更好的分离

    在进行dispatch分发之前,会对请求进行身份认证,权限检查,流量控制。

    支持定义的属性:

      authentication_classes=():列表或元组,身份认证类

      permission_classes=():列表或元组,权限检查类

      throttle_classes=():列表或元组,流量控制类              

    class Snippet_list(APIView):

      def dispatch(self, request, *args, **kwargs):

        # 请求到来之后,都需要执行dispatch方法,dispatch根据请求方式的不同,分别触发对应的get post, put等方法

        return super().dispatch(request, *args, **kwargs)

      def get(self, request, pk, format=None):

        snippet = Snippets.objects.get(pk=pk)

        serializer = SnippetSerializer(snippet, many=True)

        return Response(serialzer.data)

      def post(self, request):

        serializer = SnippetSerializer(data = request.data)

        if serializer.is_valid():

          serializer.save()

          return Response(serializer.data, status=status.HTTP_201_CREATED)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

      def delete(self, request, pk, format=None):

        snippet = Snippets.object.get(pk=pk)

        snippet.delete()

        return Response(status=status.HTTP_204_NO_CONTENT)

    配置url:

    urlpatterns = [

      url(r"^snippets/(?P<pk>[0-9]+)$", Snippet_list.as_view()),

    ]

2、mixins

  使用基于类的视图的一个最大的好处就是我们可以灵活的选择各种View,使我们的开发更加的简洁

  mixins里面对应了ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin

  这些Mixin方法,对我们上面APIView中重写的GET POST PUT DELETE进行了封装,使得我们的代码更加简洁

  

  下面是使用mixin的例子:

  GenericAPIView继承了APIView,通过GenericViewSet来构建我们的视图,然后组合ListModelMixin和CreateModelMixin来实现我们上面的代码功能

  基类提供了核心的功能,ListModelMixin和CreateModelMixin提供了.list()和.create()函数,下面我们将get和post与.list和.create绑定起来

  class snippet_list(mixins.ListModelMixin, generic.GenericAPIView):

    queryset = Snippet.objects.all()

    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):

      return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):

      return self.create(request, *args, **kwargs)

3、使用generic

  我们上面使用mixin的代码,已经非常简洁了,但是restframework给我们提供了一组混合的generic视图,可以使我们的代码 大大简化

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

  支持定义的属性:

    列表视图与详情视图通用:queryset(视图的查询集), serializer_class(视图使用的序列化器)

    列表视图专用:pagination_classes(分页控制类),filter_backends(过滤控制)

    详情页视图专用:lookup_field(查询单一数据库对象时使用的条件字段,默认为pk)

  提供的方法:

    通用:

      1)get_queryset(self):返回视图使用的查询集,是获取数据的基础,默认返回queryset,可以重写:

      def get_queryset(self):

        user = self.request.user

        return user.accounts.all()

      2)get_serializer_class(self):返回序列化器,默认返回serializer_class,可以重写,如:

        def get_serializer_class(self):

          if self.request.user.is_staff:

            return AllAccountSerializer

          return BasicAccountSerializer

      3)get_serializer(self, *args, **kwargs):返回序列化器对象

    详情视图使用:

      get_object(self):返回详情视图所需的模型类数据对象,默认使用lookup_field参数来过滤queryset

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

      class SnippetDetail(GenericAPIView):

        queryset = Snippets.objects.all()

        seriazlier_class = SnippetSerializer

        def get(self, request, pk):

          snippet = self.get_object()

          serializer = self.get_serializer(snippet)

          return Response(serialzier.data)

      url:url(r"^snippet/?P<pk>[0-9]+/$", SnippetDetail.as_view())

  五个扩展类:generics.ListAPIView, generics.CreateAPIView, generic.RetrieveAPIView, generic.UpdateAPIView, generic.DestroyAPIView,它们会继承GenericAPIView和mixin对应的视图

  

  上面可以看到generics.ListAPIView里面做的事情,它替我们继承了mixins.ListModelMixin和GenericAPIView,还重写了get方法,所以我们直接继承generic.ListAPIView,代码就会更简洁,

  只需要设置一下queryset和serializer_class即可,如下:

  class snippet_list(generics.ListAPIView):

    queryset = Snippet.objects.all()

    serializer_class = SnippetSerializer

4、视图集ViewSet

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

    list():提供一组数据

    retrieve():提供单个数据

    create():创建数据

    destroy():删除数据

    update():修改数据

  ViewSet主要是和路由搭配使用,将我们通常使用的get, post等和方法和ViewSet实现的action如list(), create()等对应上。

  action属性:

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

    def get_serializer_class(self):

      if self.action == "create":

        return SnippetCreateSerializer

      else:

        return SnippetListSerializer

  url配置:

    urlpatterns = [

      url(r"^snippet/$", SnippetViewSet.as_view({"get":"list", "post":"create"})),

      url(r"^snippet/?P<pk>[0-9]+/$", SnippetViewSet.as_view({"get":"retrive"})),

    ]

    上面url配置,是我们手动的将请求方式和action动作对应起来,其实restframework也已经帮我对应好了,它是通过Router模块来完成的,我们只需要使用router将对应的视图注册即可。

    from rest_framework.routers import DefaultRouter

    router = DefaultRouter()

    router.register(r"snippet", SnippetViewSet)

    urlpatterns = [

      url(r"^", include(router.urls))

    ]

5、Django restframework 过滤器

  如过滤文章阅读量小于100的:

  class ArticleViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):

    def get_queryset(self):

      read_nums = self.query_params.get("readNums", 0)

      if read_nums:

        return Article.objects.filter(read_nums__lt=int(read_nums))

      return Article.objects.all()

  上面这种方式,如果过滤字段少的话,可以方便使用,但是如果过滤字段多,那代码量就会很繁复了。如果还想要用简洁的代码实现大量的过滤逻辑,就需要用到其他方法,如django-filter

  pip install django-filter,并将django-filter加入到INSTALLED_APPS中。

  如:

  from django_filters.rest_framework import DjangoFilterBackend

  class ArticleViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):

    queryset = Article.objects.all()

    serializer_class = ArticleSerialzier

    filter_backends = (DjangoFilterBackend, )

    filter_fields = ("name", "title")

  这种写法相对于上面第一种写法就简单很多了,但是如果我们想要查询阅读数量大于10,小于100的文章要怎么办呢?所以这种写法还是有他的局限性,要实现这种情况的过滤,需要我们自定义过滤器:

  新建filters.py

  import django_filters

  class ArticleFilter(django_filters.rest_framework.FilterSet):

    title= django_filters.CharFilter(lookup_expr='icontains')

    readNums = django_filters.NumberFilter(lookup_expr="gte")

    class Meta:

      model = Article

      fields = ["min_readers","readNums", "clickNums"]

    说明:

      上面:model:Article---指出该类是为Article 这个model定义的过滤类

           lookup_expr------指出过滤条件,是包含,还是大于或是其他,后面会想起说明

           fields----------------指定了支持过滤的字段,如果fields中指定了字段,但是没有指定过滤方法,则表示精确查询

  view中使用:

    class SnippetViewset(mixins.ListModelMixin, viewsets.GenericViewSet):

      queryset = Article.objects.all()

      serializer_class = ArticleSerializer

      filter_backends = (DjangoFilterBackends, )

      filter_class = ArticleFilter

  

  多表过滤:                

    class Book(model.Model):

      name = model.CharField(max_length = 50)

    class Author(model.Model):

      name = model.CharField(max_length=20)

      book = model.ForeignKey(Book)

    例如上面的作者和书是一对多的关系,一个人可以写多本书。那么我们想要通过书本的名字去查询它的作者,要怎么做呢?

    class AuthorFilter(django_filters.rest_framework.FilterSet):

      book__name = django_filters.CharFilter(lookup_expr='icontains')

      class Meta:

        model = Author

        fields = ["book__name"]

    在View中使用:

      按照上面的单表查询的View写法也是可以的,这里我们通过另一种重写list的方式来完成,旨在说明自定义分页的写法。

      class AuthorViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):

        queryset = Author.objects.all()

        serializer = AuthorSerializer

        def list(self, request, *args, **kwargs):

          object = AuthorFilter(request.query_params, queryset=self.queryset)

          # 过滤后查询出的数据

          filterRecords = object.qs.count()

          # 前端传过来的参数:当前第几页

          curP = int(request.query_params.get("p", 0))

          # 前端传过来的参数:每页有几条数据

          size = int(request.query_params.get("s", 0))

          if curP and size:

            start = (curP-1)*size

            length = size

          else:

            start = 0

            length = filterRecords

          # 通过调用过滤器的返回值的qs来处理自定义分页,有兴趣的话可以去django.db.model.query.py中去看看

          object = object.qs[start:(start+length)]

          serializer = self.get_serializer(object, many = True)

          return Response(serializer.data)

    

    

Django Rest framework基础使用之View:APIView, mixins, generic, viewsets的更多相关文章

  1. Django rest framework 基础

    01: Django rest framework 基础 ​ ​ 1.1 什么是RESTful 1. REST与技术无关,代表的是一种软件架构风格(REST是Representational Stat ...

  2. 01: Django rest framework 基础

    1.1 RESTful API设计规范 参考地址: http://www.cnblogs.com/wupeiqi/articles/7805382.html   1.API与用户的通信协议,总是使用H ...

  3. Django REST framework基础:视图和路由

    DRF中的Request 在Django REST Framework中内置的Request类扩展了Django中的Request类,实现了很多方便的功能--如请求数据解析和认证等. 比如,区别于Dj ...

  4. Django Rest framework基础使用之 serializer

    rest-framework文档地址:http://www.django-rest-framework.org/ Django Rest framework是一个非常强大且灵活的工具包,用于构建web ...

  5. Django REST framework基础:认证、权限、限制

    认证.权限和限制 身份验证是将传入请求与一组标识凭据(例如请求来自的用户或其签名的令牌)相关联的机制.然后 权限 和 限制 组件决定是否拒绝这个请求. 简单来说就是: 认证确定了你是谁 权限确定你能不 ...

  6. Django REST framework基础:分页

    DRF分页组件 为什么要使用分页 我们数据表中可能会有成千上万条数据,当我们访问某张表的所有数据时,我们不太可能需要一次把所有的数据都展示出来,因为数据量很大,对服务端的内存压力比较大还有就是网络传输 ...

  7. Django REST framework基础:版本、认证、权限、限制

    1  认证.权限和限制 2  认证 2.1  自定义Token认证 2.1.1  表 2.1.2  定义一个登录视图: 2.1.3  定义一个认证类 2.1.4  视图级别认证 2.1.5  全局级别 ...

  8. Django Rest framework基础使用之Request/Response

    1.Request restframework提供了一个Request对象(rest_framework.request.Request) Request对象继承了Django默认的HttpReque ...

  9. Django REST framework基础:解析器和渲染器

    解析器 解析器的作用 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己可以处理的数据.本质就是对请求体中的数据进行解析. 在了解解析器之前,我们要先知道Accept以及ContentTy ...

随机推荐

  1. 【PSR规范专题(6)】PSR-7 HTTP消息接口【转】

    PSR-5 和 PSR-6 投票未通过所以直接跳到PSR-7了 本文档描述了在RFC 7230和RFC 7231中被描述来代表HTTP消息通用接口,以及在RFC 3986中规定的URIs语法. HTT ...

  2. VS错误:#error 指令: Please use the /MD switch for _AFXDLL builds

    我在做MFC时遇到过这个问题,解决方法如下: 修改设置:工程(Project)-> 属性(Properties)-> 配置属性(Configuration Properties)-> ...

  3. spring入门详细教程(五)

    前言 本篇紧接着spring入门详细教程(三),建议阅读本篇前,先阅读第一篇,第二篇以及第三篇.链接如下: Spring入门详细教程(一) https://www.cnblogs.com/jichi/ ...

  4. Android 自定义ListView单击事件失效

    因为自带的listView不能满足项目需求,通过实现自己的Adapter去继承ArrayAdapter 来实现自定义ListView的Item项目. 出现点击ListView的每一项都不会执行setO ...

  5. Python赋值运算符

    赋值运算符 运 算 符  说 明 举 例   展 开 形 式  =   简单的赋值运算  x=y x=y  +=  加赋值 x+=y  x=x+y -=  减赋值 x-=y  x=x-y   *= 乘 ...

  6. Linux进程优先级的处理--Linux进程的管理与调度(二十二)

    1. linux优先级的表示 1.1 优先级的内核表示 linux优先级概述 在用户空间通过nice命令设置进程的静态优先级, 这在内部会调用nice系统调用, 进程的nice值在-20~+19之间. ...

  7. Spark1.0.0 源码编译和部署包生成

    问题导读:1.如何对Spark1.0.0源码编译?2.如何生成Spark1.0的部署包?3.如何获取包资源? Spark1.0.0的源码编译和部署包生成,其本质只有两种:Maven和SBT,只不过针对 ...

  8. 从n个数里面选择m个数

    从n个数里面选择m个数 #include<iostream> #include<vector> using namespace std; vector<int> s ...

  9. Spring 的application.properties项目配置与注解

    一.项目结构介绍 如上图所示,Spring Boot的基础结构共三个文件: src/main/java  程序开发以及主程序入口 src/main/resources 配置文件 src/test/ja ...

  10. [BZOJ 2759] 一个动态树好题

    [BZOJ 2759] 一个动态树好题 题目描述 首先这是个基环树. 然后根节点一定会连出去一条非树边.通过一个环就可以解除根的答案,然后其他节点的答案就可以由根解出来. 因为要修改\(p_i\),所 ...