zoukankan      html  css  js  c++  java
  • 前后端分离djangorestframework——视图组件

    CBV与FBV

    CBV之前说过就是在view.py里写视图类,在序列化时用过,FBV就是常用的视图函数,两者的功能都可以实现功能,但是在restful规范方面的话,CBV更方便,FBV还要用request.method来判断是get,put,post等的,在CBV里要用什么就定义什么方法,根据请求的方法自动进入对应的CBV的方法里,节省了判断请求类型的过程

    View与APIView

    APIView就是在View上做了二次封装,多了一些功能而已,View是django自带的视图组件

    在 前后端分离djangorestframework——序列化与反序列化数据 这篇文章中(所以接下来用到的数据还是这篇文章里用到的数据),利用了DRF的序列化与反序列化,感受了下DRF的特性,但其实视图部分的代码还是有点冗余,假如以后有上百个url,就要给上百个url写对应的视图类,然后对数据的增删改查,都要重写一次,这样功能是可以实现,但是太low了,需要改善下

    View的第一次改版

    每次在重复书写的是数据库表的操作,序列化类的操作,以及不同的请求方式对应的视图类的方法,所以可以微调一下:

    修改数据库表和序列化类,重新定义一个类,代替操作,此后这个GenericView类可以被所有的视图类继承了,简直是一劳永逸的

    再重组请求方式对应的方法:

    访问页面看有没有问题:

    添加一个字段看看:

    成功:

    可能你访问list时还没看到数据,打开数据库库查看是有的,多刷新几次页面就有了:

    好的,把剩下的对单调数据操作的也改了

    全部代码:

    # coding:utf-8
    from django.shortcuts import HttpResponse
    from django.views import View
    from demo1 import models
    from django.core import serializers
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from demo1.serializers import BookSerializer
    
    
    class OldBookView(View):
        # def get(self, request):
        #     book_list = models.Book.objects.values("id", "title", 'pub_time','publisher')
        #     book_list = list(book_list)
        #     ret = []
        #     for field in book_list:
        #         pub_id = field['publisher']
        #         publish_obj = models.Publisher.objects.filter(id=pub_id).first()
        #         field['publisher'] = {
        #             'id':pub_id,
        #             'title':publish_obj.title
        #         }
        #         ret.append(field)
        #
        #     return JsonResponse(ret, safe=False, json_dumps_params={'ensure_ascii': False})
    
        def get(self, request):
            book_list = models.Book.objects.all()
            ret = serializers.serialize('json', book_list, ensure_ascii=False)
            return HttpResponse(ret)
    
    
    class GenericAPIView(APIView):
        query_set = None
        serializer_class = None
    
        def get_queryset(self):
            return self.query_set
    
        def get_serializer(self, *args, **kwargs):
            return self.serializer_class(*args, **kwargs)
    
    
    # Mixin字段的都是混合类,需要混合继承
    class ListModelMixin(object):
        def list(self, request):
            book_list = self.get_queryset()
            ret = self.get_serializer(book_list, many=True)
            return Response(ret.data)
    
    
    class CreateModelMixin(object):
        def create(self, request):
            serialize = self.get_serializer(data=request.data)
            if serialize.is_valid():
                # save是存储
                serialize.save()
                return Response(serialize.data)
            else:
                return Response(serialize.errors)
    
    
    class BookView(GenericAPIView, CreateModelMixin, ListModelMixin):
        query_set = models.Book.objects.all()
        serializer_class = BookSerializer
    
        def get(self, request):
            # book_list = self.get_queryset()
            # ret = self.get_serializer(book_list, many=True)
            # return Response(ret.data)
            return self.list(request)
    
        def post(self, request):
            # serialize = self.get_serializer(data=request.data)
            # if serialize.is_valid():
            #     serialize.save()
            #     return Response(serialize.data)
            # else:
            #     return Response(serialize.errors)
            return self.create(request)
    
    
    class RetrieveModelMixin(object):
        def list(self, request, id):
            book_obj = self.get_queryset().filter(id=id).first()
            ret = self.get_serializer(book_obj)
            return Response(ret.data)
    
    
    class RetrieveUpdateModelMixin(object):
        def update(self, request, id):
            book_obj = self.get_queryset().filter(id=id).first()
            # partial参数表示只对部分数据验证
            serialize = self.get_serializer(book_obj, data=request.data, partial=True)
            if serialize.is_valid():
                serialize.save()
                return Response(serialize.data)
            else:
                return Response(serialize.errors)
    
    
    class RetrieveDestoryModelMixin(object):
        def destory(self, request, id):
            book_obj = self.get_queryset().filter(id=id).exists()
            if not book_obj:
                return Response('不存在id为%s的数据,请重试' % id)
            else:
                self.get_queryset().filter(id=id).delete()
                return Response("删除成功")
    
    
    class BookEditView(GenericAPIView, RetrieveModelMixin, RetrieveUpdateModelMixin, RetrieveDestoryModelMixin):
        query_set = models.Book.objects.all()
        serializer_class = BookSerializer
    
        def get(self, request, id):
            # book_obj = models.Book.objects.filter(id=id).first()
            # ret = BookSerializer(book_obj)
            # return Response(ret.data)
            return self.list(request, id)
    
        def put(self, request, id):
            # book_obj = models.Book.objects.filter(id=id).first()
            # # partial参数表示只对部分数据验证
            # serialize = BookSerializer(book_obj, data=request.data, partial=True)
            #
            # if serialize.is_valid():
            #     # print(serialize.validated_data)
            #     # save是存储
            #     serialize.save()
            #     return Response(serialize.data)
            # else:
            #     return Response(serialize.errors)
            return self.update(request, id)
    
        def delete(self, request, id):
            # book_obj = models.Book.objects.filter(id=id).exists()
            # if not book_obj:
            #     return Response('不存在id为%s的数据,请重试' % id)
            # else:
            #     models.Book.objects.filter(id=id).delete()
            #     return Response("删除成功")
            return self.destory(request, id)
    修改视图CBV-第一版

    访问:

    修改:

    删除:

    没有问题

    View的第二次改版

    有几个视图类继承好多个类,再次微调,再定义两个类只是继承那些类,然后视图类再继承此类,相对刚才没有做任何改动,就多了一个中间父类而已

    View的第三次改版

    还有个问题,看url,都是对Book表的操作,但是却有两个视图类来处理,不太符合restful规范

    修改url,给as_view添加一个字典参数,但是默认as_view是不可以传参的,所以我们需要自己封装一个可以传参的类 

    补充,我传的as_view参数中,对单条数据修改的retrieve的get方式由之前的"get":"list"已经改成了'get':'retrieve',对应的自定义RetrieveMixin里的方法也由list改成了retrieve,因为和上面对多条数据的"get":"list" 重复了,为了防止报错,所以修改了

    定义类,修改as_view传参:

    具体的逻辑代码就不写了,因为DRF自带了

    直接用DRF定义的View——ModelViewSet

    view.py文件,ModelViewSet用的不是query_set而是queryset,需要改下:

    url要做稍微的调整,ModelViewSet用的是pk,还得把id改为pk:

    好的其他不用作任何更改

    访问:

    添加:

    修改:

    删除:

    数据库里已经没有id为7的 

     

    是的,就是这么方便

    全部代码:

     url:

    from django.urls import path, re_path, include
    # from demo1.views import BookView, BookEditView, BookModelViewSet
    from demo1.views import BookModelViewSet
    
    urlpatterns = [
        path('list', BookModelViewSet.as_view({'get': 'list', 'post': 'create'})),
        path('retrieve/<int:pk>', BookModelViewSet.as_view({'get': 'retrieve',
                                                            'put': 'update',
                                                            'delete': 'destroy'})),
    
     
    ]

    view:

    # coding:utf-8
    from demo1 import models
    from demo1.serializers import BookSerializer
    
    from rest_framework.viewsets import ModelViewSet
    
    
    class BookModelViewSet(ModelViewSet):
        queryset = models.Book.objects.all()
        serializer_class = BookSerializer

    当然,如果你还是想用自己定义那些方法类,可以这样:

    全部代码:相关的类名做了稍微的调整

    # coding:utf-8
    from django.shortcuts import HttpResponse
    from django.views import View
    from demo1 import models
    from django.core import serializers
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from demo1.serializers import BookSerializer
    
    from rest_framework.viewsets import ViewSetMixin
    
    class GenericAPIView(APIView):
        query_set = None
        serializer_class = None
    
        def get_queryset(self):
            return self.query_set
    
        def get_serializer(self, *args, **kwargs):
            return self.serializer_class(*args, **kwargs)
    
    
    # Mixin字段的都是混合类,需要混合继承
    class ListModelMixin(object):
        def list(self, request):
            book_list = self.get_queryset()
            ret = self.get_serializer(book_list, many=True)
            return Response(ret.data)
    
    
    class CreateModelMixin(object):
        def create(self, request):
            serialize = self.get_serializer(data=request.data)
            if serialize.is_valid():
                # save是存储
                serialize.save()
                return Response(serialize.data)
            else:
                return Response(serialize.errors)
    
    
    class RetrieveModelMixin(object):
        def retrieve(self, request, id):
            book_obj = self.get_queryset().filter(id=id).first()
            ret = self.get_serializer(book_obj)
            return Response(ret.data)
    
    
    class RetrieveUpdateModelMixin(object):
        def update(self, request, id):
            book_obj = self.get_queryset().filter(id=id).first()
            # partial参数表示只对部分数据验证
            serialize = self.get_serializer(book_obj, data=request.data, partial=True)
            if serialize.is_valid():
                serialize.save()
                return Response(serialize.data)
            else:
                return Response(serialize.errors)
    
    
    class RetrieveDestoryModelMixin(object):
        def destroy(self, request, id):
            book_obj = self.get_queryset().filter(id=id).exists()
            if not book_obj:
                return Response('不存在id为%s的数据,请重试' % id)
            else:
                self.get_queryset().filter(id=id).delete()
                return Response("删除成功")
    
    
    class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, RetrieveUpdateModelMixin,
                                       RetrieveDestoryModelMixin):
        pass
    
    
    class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
        pass
    
    
    class BookView(ListCreateAPIView):
        query_set = models.Book.objects.all()
        serializer_class = BookSerializer
    
        def get(self, request):
    
            return self.list(request)
    
        def post(self, request):
    
            return self.create(request)
    
    
    class BookEditView(RetrieveUpdateDestroyAPIView):
        query_set = models.Book.objects.all()
        serializer_class = BookSerializer
    
        def get(self, request, id):
            return self.retrieve(request, id)
    
        def put(self, request, id):
    
            return self.update(request, id)
    
        def delete(self, request, id):
    
            return self.destroy(request, id)
    
    
        
    class ModelViewSet(ViewSetMixin, ListModelMixin, CreateModelMixin, RetrieveUpdateModelMixin, RetrieveModelMixin,
                     RetrieveDestoryModelMixin):
        pass
    
    
    class BookModelViewSet(ModelViewSet):
        queryset = models.Book.objects.all()
        serializer_class = BookSerializer
    自定义方法类

    视图组件完毕!

    然后,有些东西是需要看源码才能看懂的,相关的源码查看:

    from rest_framework import views
    from rest_framework import generics
    from rest_framework import mixins
    from rest_framework import viewsets
    

      

    整个逻辑示图:

  • 相关阅读:
    自定义动画(仿Win10加载动画)
    jquery 仿windows10菜单效果下载
    mac os+selenium2+Firefox驱动+python3
    mac os+selenium2+chrome驱动+python3
    mac 安装scrapy
    mac 查看系统位数
    ubuntu安装 mysqldb
    ubuntu安装常用软件
    scp 时出现permission denied
    ubuntu 安装git
  • 原文地址:https://www.cnblogs.com/Eeyhan/p/10423083.html
Copyright © 2011-2022 走看看