zoukankan      html  css  js  c++  java
  • rest framework 视图,路由

     视图

      在上面序列化的组件种已经用到了视图组件,即在视图函数部分进行逻辑操作。

      但是很明显的弊端是,对每个表的增删改查加上 单条数据,需要用到 2个类 5个方法(增删改查,单数据查)才可以完整的实现,当表的数量较大的时候,就很蠢了。

      因此 rest framework 也对这个进行了多层的封装。

    源码位置 

    rest_framework.viewsets  
    rest_framework.generics  
    rest_framework.mixins 

    最底层的三个基础文件

    rest_framework.viewsets

    # 内部提供了 as_view 方法
    class ViewSetMixin(object):
        # 此方法提供了 as_view 方法可以加参数的条件
         def as_view(cls, actions=None, **initkwargs):...
    
    # 用作总的继承类 
    class GenericViewSet(ViewSetMixin, generics.GenericAPIView): ...
    
    
    # 单数据分支继承类 ,只有全数据和单数据的查看方法
    class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
                               mixins.ListModelMixin,
                               GenericViewSet):...
    
    # 全数据分支继承类,最全内置增删改查 以及 单数据查看方法 5个全都有 
    class ModelViewSet(mixins.CreateModelMixin,
                       mixins.RetrieveModelMixin,
                       mixins.UpdateModelMixin,
                       mixins.DestroyModelMixin,
                       mixins.ListModelMixin,
                       GenericViewSet):...

    rest_framework.generics

    class GenericAPIView(views.APIView):
       # queryset 数据对象传入用变量
        queryset = None  
      # 在视图中序列化工具对象传入用变量      
        serializer_class = None
    
    
    # 以下是一些增删改查的各种共功能组合 ,用于继承类使用
    
    class CreateAPIView(mixins.CreateModelMixin,
                        GenericAPIView):
    

    class ListAPIView(mixins.ListModelMixin, GenericAPIView):

    class RetrieveAPIView(mixins.RetrieveModelMixin, GenericAPIView):

    class DestroyAPIView(mixins.DestroyModelMixin, GenericAPIView):

    class UpdateAPIView(mixins.UpdateModelMixin, GenericAPIView):

    class ListCreateAPIView(mixins.ListModelMixin, mixins.CreateModelMixin, GenericAPIView):

    class RetrieveUpdateAPIView(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, GenericAPIView):

    class RetrieveDestroyAPIView(mixins.RetrieveModelMixin, mixins.DestroyModelMixin, GenericAPIView):

    class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, GenericAPIView):

     rest_framework.mixins 

        内置的操作方法 增删改查 单行数据查询都在这里

    class CreateModelMixin(object): ...
    
    class ListModelMixin(object): ...
    
    class RetrieveModelMixin(object): ...
    
    class UpdateModelMixin(object): ...
    
    class DestroyModelMixin(object): ...

    彼此继承关系图

    基于底层三类进行了两轮封装

      GenrericViewSet 封装了 GenericAPIView 和 ViewSetMixin ,于是获得了 传入对象以及 重写 as_view 的功能

      ModelViewSet 封装了 GenrericViewSet  和  mixins ,在 GenrericViewSet 的基础上 又获得了 增删改查方法的集成 

    最初始最全面也是最笨的方式操作表

    方式1 2类5方法无判断

    对于全部数据的查询以及数据的创建不需要带参数,设计为一条URL

    其他单数据的查看编辑和删除在设计一条URL

    两条URL 分别对应两个类  

    全部的内容:

      写全了就是 2个类 ,加起来一共5方法 

     各类中的请求对应方式

    class BookView(APIView):
        def get(self,request):        # 对所有数据进行查看
            book_list=Book.objects.all()
            bs=BookModelSerializers(book_list,many=True,context={'request': request})
            return Response(bs.data)
        def post(self,request):        # 对数据进行创建提交 
            # post请求的数据
            bs=BookModelSerializers(data=request.data)
            if bs.is_valid():
                print(bs.validated_data)
                bs.save()    # .create()方法
                return Response(bs.data)
            else:
                return Response(bs.errors)
    
    
    class BookDetailView(APIView):
    
        def get(self,request,id):    # 对单条数据进行查看
    
            book=Book.objects.filter(pk=id).first()
            bs=BookModelSerializers(book,context={'request': request})
            return Response(bs.data)
    
        def put(self,request,id): # 对单条数据进行更新
            book=Book.objects.filter(pk=id).first()
            bs=BookModelSerializers(book,data=request.data)
            if bs.is_valid():
                bs.save()     # .updata()
                return Response(bs.data)
            else:
                return Response(bs.errors)
        
        def delete(self,request,id):    # 删除数据 
            Book.objects.filter(pk=id).delete()
            return Response()

    方式2 一类5方法带判断

    只写一个类,内含5方法,在get 的时候进行一次判断即可

    class IndexView(views.APIView):
    
        def get(self,request,*args,**kwargs):
            pk = kwargs.get('pk')
            if pk:
                pass # 获取单条信息
            else:
                pass # 获取列表信息
    
        def post(self,request,*args,**kwargs):
            pass
    
        def put(self,request,*args,**kwargs):
            pass
    
        def patch(self,request,*args,**kwargs):
            pass
    
        def delete(self,request,*args,**kwargs):
                    pass
    class SchoolView(APIView):
        def get(self, request, *args, **kwargs):
            query_set = models.School.objects.all()  
            ser_obj = app01_serializers.SchoolSerializer(query_set, many=True)
            return Response(ser_obj.data)
    
    
    class SchoolDetail(APIView):
        def get(self, request, pk, *args, **kwargs):
            obj = models.School.objects.filter(pk=pk).first()
            ser_obj = app01_serializers.SchoolSerializer(obj)
            return Response(ser_obj.data)

    第一次整合

       利用GenericeAPIView 传入 queryset对象以及 序列化对象, 再利用内置的 mixins 中的操作方法省去操作代码

    from rest_framework.generics import GenericAPIView
    from rest_framework import.mixins
    
    
    class SchoolView(GenericAPIView, mixins.ListModelMixin):
        queryset = models.School.objects.all()
        serializer_class = app01_serializers.SchoolSerializer
    
        def get(self, request, *args, **kwargs):
            return self.list(request, *args, **kwargs)
    
    
    class SchoolDetail(GenericAPIView, mixins.RetrieveModelMixin, mixins.CreateModelMixin):
        queryset = models.School.objects.all()
        serializer_class = app01_serializers.SchoolSerializer
    
        def get(self, request, pk, *args, **kwargs):
            return self.retrieve(request, pk, *args, **kwargs)
    
        def post(self, request, *args, **kwargs):
            return self.create(request, *args, **kwargs)

    路由依旧是分成两条,单数据和多数据分开

    url(r'school/$', views.SchoolView.as_view()),
    url(r'school/(?P<pk>d+)/$', views.SchoolDetail.as_view()),

    第二次整合

      利用GenericeAPIView 传入 queryset对象以及 序列化对象, 再利用内置的  generics 中的操作方法省去操作代码

    from rest_framework.generics import ListCreateAPIView,RetrieveUpdateDestroyAPIView
    class SchoolView(ListCreateAPIView):
        queryset = models.School.objects.all()
        serializer_class = app01_serializers.SchoolSerializer
    
    
    class SchoolDetail(RetrieveUpdateDestroyAPIView):
        queryset = models.School.objects.all()
        serializer_class = app01_serializers.SchoolSerializer

      路由依旧是分成两条,单数据和多数据分开,同第一次整合无区别

    url(r'school/$', views.SchoolView.as_view()),
    url(r'school/(?P<pk>d+)/$', views.SchoolDetail.as_view()),

    终极版

       直接继承最终的 ModelViewSet 继承类 ,ModelViewSet  在 ViewSetMixin 类 之上,可以重写 as_view 方法能够添加参数

    from rest_framework.viewset import ModelViewSet
    class SchoolView(ModelViewSet):
        queryset = models.School.objects.all()
        serializer_class = app01_serializers.SchoolSerializer

      因为视图被极大的压缩,参数的传递交给了 as_view 来处理,因此 url 会变得比以往复杂,url 还可以进一步封装,详情往下看路由部分

    url(r'school/$', views.SchoolView.as_view({
        "get": "list",
        "post": "create",
    })),
    url(r'school/(?P<pk>d+)/$', views.SchoolView.as_view({
        'get': 'retrieve',
        'put': 'update',
        'patch': 'partial_update',
        'delete': 'destroy'
    })),

    终极版自定制

    class P2(PageNumberPagination):
        page_size = 3  #每一页显示的条数
        page_query_param = 'page' #获取参数中传入的页码
        page_size_query_param = 'size' #获取url参数中每页显示的数据条数
    
        max_page_size = 5
    
    class IndexSerializer(ModelSerializer):
        class Meta:
            model = models.UserInfo
            fields = "__all__"
    
    class IndexView4(ModelViewSet):
        queryset = models.UserInfo.objects.all()
        serializer_class = IndexSerializer
        pagination_class = P2
    
        def list(self, request, *args, **kwargs):
            '''获取get请求的所有'''
            pass
    
        def retrieve(self, request, *args, **kwargs):
            '''查看单条数据'''
            pass
        def destroy(self, request, *args, **kwargs):
            '''删除DELETE'''
            pass
        def create(self, request, *args, **kwargs):
            '''添加数据POST'''
            pass
        def update(self, request, *args, **kwargs):
            '''全部修改PUT'''
            pass
        def partial_update(self, request, *args, **kwargs):
            '''局部修改PATCH'''
            pass
    

    二次整理版本( 浓缩版 )

        """
        继承结构 (功能↓) (封装↑)
                ModelViewSet/ReadOnlyModelViewSet
        generics.xxx                        GenericViewSet
        mixins.xxx                          GenericAPIView                              
                                            APIView  
                                            ViewSetMixin
    
                           
        基础的四个功能组件(每个都有自己独有功能)              
            APIView(View) 
                啥都没有, 全部手写去吧
            
            ViewSetMixin(object)
                提供了 as_view 的重写
                以及 initialize_request 里面很多的 action 
            
            mixins.xxx(object)
                提供以下的 5 个基础的增删改查方法, 
                CreateModelMixin - create()    post() 
                ListModelMixin - list()    get()
                RetrieveModelMixin - retrieve()   patch() 
                DestroyModelMixin - destroy()   delete()
                UpdateModelMixin - update()    put() 
                
            GenericAPIView(views.APIView) 
                提供了以下字段的封装, 不需要手写了
                queryset = None             数据库对象
                serializer_class = None     序列化对象
                lookup_field = 'pk'         默认查询字段, 默认是 id 
                lookup_url_kwarg = None     查询单一数据时URL中的参数关键字名称, 默认与look_field相同
                filter_backends = api_settings.DEFAULT_FILTER_BACKENDS      过滤
                pagination_class = api_settings.DEFAULT_PAGINATION_CLASS    分页器选择
        
        进阶的两个(对基础组件的一层封装) 
            GenericViewSet(ViewSetMixin, generics.GenericAPIView) 
                集合了 as_view 以及 可写参数
        
            generics.xxxx.....(mixins.xxxxx,GenericAPIView)
                各式的组合增删改查, 以及附加参数功能
                CreateAPIView(mixins.CreateModelMixin,GenericAPIView)
                ListAPIView(mixins.ListModelMixin,GenericAPIView)  
                RetrieveAPIView(mixins.RetrieveModelMixin,GenericAPIView)
                DestroyAPIView(mixins.DestroyModelMixin,GenericAPIView)
                UpdateAPIView(mixins.UpdateModelMixin,GenericAPIView)
                ListCreateAPIView(mixins.ListModelMixin,mixins.CreateModelMixin,GenericAPIView)
                RetrieveUpdateAPIView(mixins.RetrieveModelMixin,mixins.UpdateModelMixin,GenericAPIView)
                RetrieveDestroyAPIView(mixins.RetrieveModelMixin,mixins.DestroyModelMixin,GenericAPIView)
                RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,GenericAPIView)
            
        终极的两个(二级封装更加方便了)
            ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
                               mixins.ListModelMixin,
                               GenericViewSet)
                其他都有, 只能读取
            ModelViewSet(mixins.CreateModelMixin,
                       mixins.RetrieveModelMixin,
                       mixins.UpdateModelMixin,
                       mixins.DestroyModelMixin,
                       mixins.ListModelMixin,
                       GenericViewSet)
                全部都有, 集合了所有的请求方式
        
        视图继承的选择
            一阶段 
                View 你这是在用 django
            二阶段
                APIView 在用 drf 了.但是是最基础的方式
            三阶段
                GenericAPIView 很多参数可以用了, 但是所有方法自己写
            四阶段
                GenericAPIView + mixins 能用参数了, 不用写各请求的逻辑了. 但是还要写个壳子
            五阶段
                GenericAPIView + generics.xxx 能用参数, 而且灵活组合自己的请求类型, 壳子也不用写了
            六阶段
                GenericViewSet + generics.xxx 能用参数, 灵活组请求类型, 重写了as_view, 获得高级路由功能
            七阶段
                ReadOnlyModelViewSet 前面有的我都有. 但是我只能读
            八阶段
                ModelViewSet 我全都有
        """

    路由

    完全自定义路由

    单数据,全数据的两只路由加 带格式的两只路由一共4条路由

    # http://127.0.0.1:8000/api/v1/auth/
    url(r'^auth/$', views.AuthView.as_view()),
    
    # http://127.0.0.1:8000/api/v1/auth.json # 想要让页面显示json格式 url(r'^auth.(?P<format>[a-z0-9]+)$', views.AuthView.as_view()),
    # http://127.0.0.1:8000/api/v1/auth/1/ url(r'^auth/(?P<pk>d+)/$', views.AuthView.as_view()),
    # http://127.0.0.1:8000/api/v1/auth/1.json url(r'^auth/(?P<pk>d+).(?P<format>[a-z0-9]+)$', views.AuthView.as_view()),

    class AuthView(views.APIView): def get(self,request,*args,**kwargs): return Response('...')

    半自动路由

    重写了 as_view 方法后,可以在as_view方法中加入参数传递方法对应,手动指定响应方式和视图方法的映射

    url(r'^index/$', views.IndexView.as_view({'get':'list','post':'create'})),
    url(r'^index.(?P<format>[a-z0-9]+)$', views.IndexView.as_view({'get':'list','post':'create'})),
    url(r'^index/(?P<pk>d+)/$', views.IndexView.as_view({'get':'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),
    url(r'^index(?P<pk>d+).(?P<format>[a-z0-9]+)$', views.IndexView.as_view({'get':'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),
    
    class IndexView(viewsets.ModelViewSet):
        queryset = models.UserInfo.objects.all()
        serializer_class = IndexSerializer
        pagination_class = P2

    全自动路由

    完全自动生成所有的 url,且自动创建了视图关系

    # 注册前的准备,做一个实例化对象
    routers=routers.DefaultRouter()
    # 注册需要加两个参数  ("url前缀",视图函数)
    routers.register("authors",views.AuthorModelView)
    routers.register("books",views.AuthorModelView)
    
    """ 会自动帮你生成 4 条 url ^authors/$ [name='author-list'] ^authors.(?P<format>[a-z0-9]+)/?$ [name='author-list'] ^authors/(?P<pk>[^/.]+)/$ [name='author-detail'] ^authors/(?P<pk>[^/.]+).(?P<format>[a-z0-9]+)/?$ [name='author-detail'] # 响应器控制 """ urlpatterns = [ # url(r'^authors/$', views.AuthorModelView.as_view({"get":"list","post":"create"}),name="author"), # url(r'^authors/(?P<pk>d+)/$', views.AuthorModelView.as_view({"get":"retrieve","put":"update","delete":"destroy"}),name="detailauthor"), # 上面的两条被简化成了下面一句话 url(r'', include(routers.urls)), ]
    router = DefaultRouter()
    router.register('index',views.IndexViewSet)
    urlpatterns = [
        url(r'^', include(router.urls)),
    ]
    
    
    class IndexViewSet(viewsets.ModelViewSet):
        queryset = models.UserInfo.objects.all()
        serializer_class = IndexSerializer
        pagination_class = P2
        
        
        
    class IndexSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.UserInfo
            fields = "__all__"
  • 相关阅读:
    C#-创建自定义双击事件
    C#-设置button颜色
    C#-动态生成40个按钮,大小(20,20),要求每行6个放置
    推荐系统相关算法(1):SVD
    SVD在推荐系统中的应用
    个性化推荐研究(四)之如何利用用户行为数据
    推荐系统开源软件列表
    推荐系统中所使用的混合技术介绍
    协同过滤算法
    转:[大数据竞赛]算法讨论
  • 原文地址:https://www.cnblogs.com/shijieli/p/10273610.html
Copyright © 2011-2022 走看看