DRF 视图

DRF 视图

基于类的视图的一个主要优点是它们允许您组合可重用行为的方式。REST框架通过提供许多提供常用模式的预构建视图来利用这一点。

REST框架提供的通用视图允许您快速构建与您的数据库模型紧密相关的API视图。

如果通用视图不适合您的API需求,您可以直接使用常规APIView类,或者重用通用视图使用的mixins和基类来组成您自己的可重用通用视图集。

初始态


class PublisherListView(APIView):

    def get(self, request):
        queryset = models.Publisher.objects.all()
        ser_obj = PublisherModelSerializer(queryset, many=True)
        return Response(ser_obj.data)

    def post(self, request):
        ser_obj = PublisherModelSerializer(data=self.request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response('ok')
        else:
            return Response(ser_obj.errors)


class AuthorListView(APIView):

    def get(self, request):
        queryset = models.Author.objects.all()
        ser_obj = AuthorModelSerializer(queryset, many=True)
        return Response(ser_obj.data)

    def post(self, request):
        ser_obj = AuthorModelSerializer(data=self.request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response('ok')
        else:
            return Response(ser_obj.errors)

进化

python mixin(混合类):不能单独使用,和其它类搭配起来使用(利用了Python支持多继承)

class GenericView(APIView):
    queryset = None
    serializer = None

    def get_queryset(self):
        return self.queryset.all()


class ListMixin(object):
    # python mixin(混合类):不能单独使用,和其它类搭配起来使用(利用了Python支持多继承)
    def get(self, request):
        queryset = self.get_queryset()
        ser_obj = self.serializer(queryset, many=True)
        return Response(ser_obj.data)


class CreateMixin(object):
    def post(self, request):
        ser_obj = self.serializer(data=self.request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response('ok')
        else:
            return Response(ser_obj.errors)


class AuthorListView(GenericView, ListMixin, CreateMixin):
    queryset = models.Author.objects.all()
    serializer = AuthorModelSerializer


class PublisherListView(GenericView, ListMixin, CreateMixin):
    queryset = models.Publisher.objects.all()
    serializer = PublisherModelSerializer

超进化

提取混合类,将混合类继续组合!

把增删改查查五动作拆分出来,写成独立的混合。

class GenericView(APIView):
    queryset = None
    serializer_class = None

    def get_queryset(self):
        return self.queryset.all()


class ListMixin(object):
    # python mixin(混合类):不能单独使用,和其它类搭配起来使用(利用了Python支持多继承)
    def get(self, request):
        queryset = self.get_queryset()
        ser_obj = self.serializer_class(queryset, many=True)
        return Response(ser_obj.data)


class CreateMixin(object):
    # python Mixin 混合类,不可单独使用
    def post(self, request):
        ser_obj = self.serializer_class(data=self.request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response('ok')
        else:
            return Response(ser_obj.errors)


class RetrieveMixin(object):
    def get(self, request, pk):
        obj = self.get_queryset().filter(pk=pk).first()
        if obj:
            pass
            ser_boj = self.serializer_class(obj)
            return Response(ser_boj.data)
        else:
            return Response('无效id')


class UpdateMixin(object):
    def put(self, request, pk):
        obj = self.get_queryset().filter(pk=pk).first()
        if obj:
            ser_boj = self.serializer_class(instance=obj, data=self.request.data, partial=True)
            if ser_boj.is_valid():
                ser_boj.save()
                return Response(ser_boj.data)
            else:
                return Response(ser_boj.errors)
        else:
            return Response('无效id')


class DestroyMixin(object):
    def delete(self, request, pk):
        obj = self.get_queryset().filter(pk=pk).first()
        if obj:
            obj.delete()
            return Response('删除成功')
        else:
            return Response('无效id')


class AuthorListView(GenericView, ListMixin, CreateMixin):
    queryset = models.Author.objects.all()
    serializer_class = AuthorModelSerializer


class AuthorDetailView(GenericView, RetrieveMixin, UpdateMixin, DestroyMixin):
    queryset = models.Author.objects.all()
    serializer_class = AuthorModelSerializer


class PublisherListView(GenericView, ListMixin, CreateMixin):
    queryset = models.Publisher.objects.all()
    serializer_class = PublisherModelSerializer


class PublisherDetailView(GenericView, RetrieveMixin, UpdateMixin, DestroyMixin):
    queryset = models.Publisher.objects.all()
    serializer_class = PublisherModelSerializer

其实内置已经提供了

from rest_framework.generics import ListAPIView, CreateAPIView, RetrieveAPIView, UpdateAPIView, DestroyAPIView

究极进化

一张表要写两个视图,定义两次 queryset和serializer_class 重复!

from rest_framework.viewsets import GenericViewSet

GenericViewSet重写了as_view()方法,实现了根据请求的方法执行具体的类方法

路由注册的时候,利用actions参数,实现路由的定向分发 而不是简单的 反射

路由都重复写两条!

还可以利用内置的DefaultRouter来实现路由的注册

from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register('pulisher', views.PublisherViewSet)

urlpatterns += router.urls

视图

from rest_framework.viewsets import ModelViewSet


class PublisherViewSet(ModelViewSet):
    queryset = models.Publisher.objects.all()
    serializer_class = PublisherModelSerializer

路由

    url(r'^publishers/$', views.PublisherViewSet.as_view(actions={'get': 'list', 'post': 'create'})), # 出版社列表
    url(r'^publishers/(?P<pk>\d+)/$', views.PublisherViewSet.as_view(
        actions={'get': 'retrieve', 'post': 'update', 'delete': 'destroy'})), # 出版社详情

总结

一般使用

一张表,两个视图

from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView


class PublisherListView(ListCreateAPIView):
    queryset = models.Publisher.objects.all()
    serializer_class = PublisherModelSerializer


class PublisherDetailView(RetrieveUpdateDestroyAPIView):
    queryset = models.Publisher.objects.all()
    serializer_class = PublisherModelSerializer

一张表,一个视图

from rest_framework.viewsets import ModelViewSet


class PublisherViewSet(ModelViewSet):
    queryset = models.Publisher.objects.all()
    serializer_class = PublisherModelSerializer

路由:

    url(r'^publishers/$', views.PublisherViewSet.as_view(actions={'get': 'list', 'post': 'create'})),
    url(r'^publishers/(?P<pk>\d+)/$', views.PublisherViewSet.as_view(
        actions={'get': 'retrieve', 'post': 'update', 'delete': 'destroy'})),

view ,django CBV的view,拥有 dispatch() 方法,通过反射向CBV中分发请求

APIView,继承view ,重写了 dispatch() 方法,增加了 内容协商,版本控制,认证,权限,限制功能,并将原来 django 的 HttpRequest对象 更新为 rest_framework 重写的 Request 对象,在重写的 Request 对象中,原来的 request 对象变为 request._request ,还新增了 request.data ,为根据 request.content_type 解析出的数据, request.query_params 为URL中的参数

GenericAPIView,继承于APIView ,增加了 get_queryset() get_serializer() paginator()方法,对应的功能是 queryset ,序列化,分页,只需赋予 queryset对象,序列化类,分页类即可自动完成操作。

ViewSetMixin ,重写 as_view()方法,根据路由url中 action参数直接将 一个请求绑定一个方法,然后再用 GenericAPIView 中的 dispatch() 方法进行分发

GerericViewSet ,继承于 ViewSetMixin ,GenericAPIView

ListModelMixin,实现 list() 方法,返回一个queryset的列表,对应于 get

CreateModelMixin, 实现create()方法 ,创建一个实例,对应于 post

RetrieveModelMixin,实现retrieve()方法, 返回一个具体实例,对应于 get

UpdateModelMixin,实现update()方法 ,对某个实例进行更新,对应于 put/patch

DestroyModelMixin,实现destroy()方法,删除某个实例,对应于 delete

ModelViewSet , 继承于 GerericViewSet ,ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin

posted @ 2019-08-16 16:29  写bug的日子  阅读(114)  评论(0编辑  收藏  举报