• Django Rest framework 之 视图


    在之前的django rest framework其他组件中,在视图函数中继承类都是rest_framework.view.APIView,这个APIView是继承的django中的View并且做了封装和方法重写的。 那么在django rest framework中,还有有没有提供其他的类能够继承?

    一、GenericAPIView

    GenericAPIViewdjango rest framework中根据APIView又做了一层封装。则继承关系就变成了GenericAPIView——>APIView——>View

    from rest_framework.generics import GenericAPIView
    
    class GenericView(GenericAPIView):
        queryset = Role.objects.get_queryset().order_by('id')
        serializer_class = PagerSerializer
        pagination_class = PageNumberPagination
    
        def get(self,request,*args,**kwargs):
    
            roles = self.get_queryset()
            pager_roles = self.paginate_queryset(roles)
            ser = self.get_serializer(instance=pager_roles,many=True)
            return Response(ser.data)
    

    这里实现的功能和django rest framework 之 分页中的功能一样,先获取数据,分页,序列化返回。不同的是,这里由于封装的作用,GenericAPIView的内部的一些方法会根据会自动的获取数据库查询结果并分页和序列化。

    • get_queryset(): 会获取数据库查询结果,也就是queryset
    • paginate_queryset(roles):会根据重写的pagination_class属性获取分页类进行分页操作,另外如果这里没有重写,会自动到settings.py配置文件去找
    • self.get_serializer():就是根据分页后的对象进行数据的序列化,也会先找到序列化类

    二、GenericViewSet

    1、源码分析

    GenericViewSet实际上使用了多继承和Mixin模式,也就是说GenericViewSet同时继承了ViewSetMixin, generics.GenericAPIView两个父类

    # rest_frameworkviewsets.py 源码
    
    class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
        pass
    

    GenericViewSet中由于类继承的先后顺序的关系,会先执行ViewSetMixin类中相关方法。而GenericAPIView类中的相关方法会被忽略。

    2、路由

    在执行之前要更改一下路由系统

    from django.conf.urls import url
    
    from .views import *
    app_name = 'api'
    
    urlpatterns = [
        url(r'^generic/$', GenericView.as_view()),
        url(r'^genericset/$', GenericSetView.as_view({'get': 'list', 'post': 'create'})),
    ]
    
    

    由于在GenericViewSet的内部重写了as_view方法,且继承关系又先于GenericAPIView类,所以会进入GenericViewSetas_view方法。但是在as_view方法中,对路由系统做了略微的改动,需要对方法,做一一映射关系。即'get': 'list', 'post': 'create',get(获取单条数据)请求,会进入子类的list方法,而create(创建对象)方法则代表了post请求。

    3、视图

    视图中基本上和上面一样,只不过更改了不同http请求方法的对应类方法名

    from rest_framework.viewsets import GenericViewSet
    
    class GenericSetView(GenericViewSet):
        queryset = Role.objects.get_queryset().order_by('id')
        serializer_class = PagerSerializer
        pagination_class = PageNumberPagination
    
        def list(self,request,*args,**kwargs):
            # 获取数据
            roles = self.get_queryset() # models.Role.objects.all()
            # [1, 1000,]     [1,10]
            pager_roles = self.paginate_queryset(roles)
            # 序列化
            ser = self.get_serializer(instance=pager_roles,many=True)
            return Response(ser.data)
    
        def create(self, request, *args, **kwargs):
            ret = {}
            try:
                title = request.data['title']
                Role.objects.create(title=title)
                print('success')
            except Exception as e:
                print(e)
    
    

    4、测试

    <1>、测试一

    http://127.0.0.1:8000/api/genericsetget方法获取数据时,返回正常结果

    <2>、测试二

    http://127.0.0.1:8000/api/genericset/,表示发送post请求添加单条数据,数据添加成功

    三、ModelSetView

    1、源码分析

    ModelSetView做的更彻底,他又一次继承了GenericViewSet,并且在此之前又继承了其他几个类,因此功能更多,变成了ModelViewSet——>GenericViewSet——>APIView——>View

    class ModelViewSet(mixins.CreateModelMixin,
                       mixins.RetrieveModelMixin,
                       mixins.UpdateModelMixin,
                       mixins.DestroyModelMixin,
                       mixins.ListModelMixin,
                       GenericViewSet):
      
        pass
    

    从这些类的名字可以大概看出,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,.ListModelMixin,分别对应,创建,获取单条数据,更新,删除,或许多条数据。

    2、路由

    from django.conf.urls import url
    from django.urls import path
    
    from .views import *
    app_name = 'api'
    
    urlpatterns = [
        url(r'^modelset/(?P<pk>d+)/$', ModelSetView.as_view({'get': 'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),
    ]
    
    

    由于在获取,删除,更新数据的时候需要这顶数据的唯一标识,这里是pk主键,因此需要在url中增加正则匹配。

    3、视图

    在视图中,并没有增加相应的增删改查的逻辑却能完成相应的功能,这是因为继承的mixin类中,已经有一一对应的方法,视图类会自动调用父类的方法。

    from rest_framework.viewsets import ModelViewSet
    
    class ModelSetView(ModelViewSet):
        queryset = Role.objects.get_queryset().order_by('id')
        serializer_class = PagerSerializer
        pagination_class = PageNumberPagination
    
    

    获取第九条数据,返回结果

    4、自定义

    ModelSetView中看到,继承了多个mixin类,而这些类又分别封装了不同的对应于增删给查的方法,因此如果想要自定义一个接口,实现部分http方法,就可以根据需要继承不同的mixin

    mixins.CreateModelMixin,
    mixins.RetrieveModelMixin,
    mixins.UpdateModelMixin,
    mixins.DestroyModelMixin,
    mixins.ListModelMixin,
    
  • 相关阅读:
    hdu 4476 Cut the rope (2-pointer && simulation)
    hdu 1286 找新朋友 (容斥原理 || 欧拉函数)
    函数存储的另一种思路
    grunt 入门 应用grunt对代码进行压缩
    sublime flatLand 主题
    如何应用r.js对requirejs下的js代码合并
    如何在requirejs下引用bootstrap
    学习在requirejs下如何使用underscore.js模板
    应用js函数柯里化currying 与ajax 局部刷新dom
    js 函数arguments一种用法
  • 原文地址:https://www.cnblogs.com/welan/p/9954228.html
Copyright © 2020-2023  润新知