返回顶部

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_framework\viewsets.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,

posted on 2018-11-13 19:40  weilanhanf  阅读(3084)  评论(0编辑  收藏  举报

导航