zoukankan      html  css  js  c++  java
  • REST-framework快速构建API--四部曲

    代码目录结构:

     

    一、使用原生APIView

    使用rest-framework原生的APIView实现过程:

    以url(r'^books/$', views.BookView.as_view(),name="books")为例进行流程分析,

    • 1、views.BookView.as_view()==>APIView的as_view方法==>父类【View】的as_view方法
    • 2、View的as_view方法实际上是返回了View下的view方法
    • 3、view实际上是执行了dispatch方法
    • 4、dispatch执行过程是去找对应的get/post/put/delete/patch方法

    代码实现如下:

    urls文件

    PublishView用于处理publishes的get和post,获取多个资源的情况

    PublishDetailView用于处理publishes/1/的get、put、delete,获取单个资源的情况

    url(r'^publishes/$', views.PublishView.as_view(),name="publish"),
    url(r'^publishes/(?P<pk>d+)/$', views.PublishDetailView.as_view(),name="detailpublish"), 
    

      

    views文件

    使用rest-framework原生的APIView,按照上面说的流程,最后进入dispatch方法,所以只需要我们自己重写get/post/put/delete等方法即可。

    from rest_framework.views import APIView
    # Publish表
    class PublishView(APIView):
        def get(self,request):
      
            publish_list = Publish.objects.all()
            ps = PublishModelSerializers(publish_list, many=True)
            return Response(ps.data)
    
        def post(self,request):
    
            # post请求的数据
            ps = PublishModelSerializers(data=request.data)
            if ps.is_valid():
                print(ps.validated_data)
                ps.save()  # create方法
                return Response(ps.data)
            else:
                return Response(ps.errors)
    class PublishDetailView(APIView):
        def get(self, request, pk):
    
            publish = Publish.objects.filter(pk=pk).first()
            ps = PublishModelSerializers(publish)
            return Response(ps.data)
    
        def put(self, request, pk):
            publish = Publish.objects.filter(pk=pk).first()
            ps = PublishModelSerializers(publish, data=request.data)
            if ps.is_valid():
                ps.save()
                return Response(ps.data)
            else:
                return Response(ps.errors)
    
        def delete(self, request, pk):
            Publish.objects.filter(pk=pk).delete()
    
            return Response()
    

      

    serializer文件

    通过ModelSerializer类,指定model和fields进行序列化操作。

    from rest_framework import serializers
    
    from app01.models import *
    # 为queryset,model对象做序列化
    class PublishSerializers(serializers.Serializer):
        name = serializers.CharField()
        email = serializers.CharField()
    
    
    class PublishModelSerializers(serializers.ModelSerializer):
        class Meta:
            model=Publish
            fields="__all__"
    

      

    原生APIView的缺点

    针对每个model,需要自己写API的各种方法,代码重复程度很高。

    进一步解决办法:使用mixins

    二、使用mixins

    mixins在上一步的基础上进行了进一步的封装,也就是把多资源情况下的GET/POST以及单资源情况下的GET/POST/PUT/DELETE进行了再次封装,只要我们指定集成的类,然后重写对应的方法即可,urls也不用变更。

    from rest_framework import mixins
    from rest_framework import generics
    
    class AuthorView(mixins.ListModelMixin,mixins.CreateModelMixin,generics.GenericAPIView):
        queryset=Author.objects.all()
        serializer_class =AuthorModelSerializers
    
        def get(self,request, *args, **kwargs):
            return self.list(request, *args, **kwargs)
        def post(self,request, *args, **kwargs):
            return self.create(request, *args, **kwargs)
    
    
    class AuthorDetailView(mixins.RetrieveModelMixin,mixins.DestroyModelMixin,mixins.UpdateModelMixin,generics.GenericAPIView):
        queryset = Author.objects.all()
        serializer_class = AuthorModelSerializers
    
        def get(self,request,*args, **kwargs):
            return self.retrieve(request,*args, **kwargs)
    
        def delete(self,request,*args, **kwargs):
            return self.destroy(request,*args, **kwargs)
    
        def put(self,request,*args, **kwargs):
            return self.retrieve(request,*args, **kwargs)
    

      

    使用mixins还是有代码重复的缺点,每个model表都需要重写这一堆方法和类。

     

    三、使用generics

    使用generics可以很好的避免上面的问题,他直接包含了多资源和单资源情况下的所有方法,而不需要重写get、post、put、delete方法,甚至还包括patch方法。

    from rest_framework import mixins
    from rest_framework import generics
    
    
    class AuthorView(generics.ListCreateAPIView):
        queryset=Author.objects.all()
        serializer_class =AuthorModelSerializers
    
    class AuthorDetailView(generics.RetrieveUpdateDestroyAPIView):
        queryset = Author.objects.all()
        serializer_class = AuthorModelSerializers
    

      但是这里还有一个缺点,就是单资源和多资源的视图函数以及url都是两份,是不是可以进行一步封装呢?

    四、使用viewsets

    使用viewsets可以通过在as_view中传参进一步简化操作。

    在as_view中传入{动作:方法}的字典给action参数,然后通过getattr和setattr方法进行参数解析,然后通过dispatch中执行对应的方法。

    urls文件

    url(r'^books/$', views.BookViewSet.as_view({"get":"list","post":"create"}),name="book_list"),
        url(r'^books/(?P<pk>d+)$', views.BookViewSet.as_view({
                    'get': 'retrieve',
                    'put': 'update',
                    'patch': 'partial_update',
                    'delete': 'destroy'
                }),name="book_detail"),
    

      

    views文件

    class BookViewSet(viewsets.ModelViewSet):
        queryset = Book.objects.all()
        serializer_class = BookSerializers
    

      

    这就是最终版本,对于一个model表,url两个,一个ModelViewSet类就可以轻易的实现一个API!

    进一步简化

    我们可以看到urls里面看上去是不是很乱的样子,其实,rest-framework也已经解决了这个脏乱差的问题,通过使用routers!

    urls文件修改

    以books为例:

    from django.conf.urls import url,include
    from django.contrib import admin
    from rest_framework import routers
    from app01 import views
    
    
    #router实例化,并将Viewset进行注册
    router = routers.DefaultRouter()
    router.register(r'books',views.BookViewSet)
    
    
    #路由控制
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^publishes/$', views.PublishView.as_view(),name="publish"), #  View:view(request)=====APIView:dispatch()
        url(r'^publishes/(?P<pk>d+)/$', views.PublishDetailView.as_view(),name="detailpublish"), #  View:view(request)=====APIView:dispatch()
    
        url(r'',include(router.urls)),
            
    ]
    

      

    其他Viewset需要实例化,同样的操作即可,urls的最终结果为:

    from django.conf.urls import url,include
    from django.contrib import admin
    from rest_framework import routers
    from app01 import views
    
    
    #router实例化,并将Viewset进行注册
    router = routers.DefaultRouter()
    router.register(r'books',views.BookViewSet)
    router.register(r'books',views.PublishViewSet)
    
    
    #路由控制
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'',include(router.urls)),
            
    ]
    

      是不是很简洁?

  • 相关阅读:
    【Javascript】javascript学习 二十二 JavaScript 对象简介
    【Javascript】javascript学习 二十六 JavaScript Boolean(逻辑)对象
    【Javascript】javascript学习 二十九 JavaScript HTML DOM 对象
    【Javascript】javascript学习 二十八 JavaScript RegExp 对象
    【Javascript】javascript学习 二十一 JavaScript 指导方针
    【Javascript】javascript学习 二十三 JavaScript 字符串(String)对象
    【Javascript】javascript学习 三十 JavaScript 浏览器检测
    【Javascript】javascript学习 二十五 JavaScript Array(数组)对象
    【Javascript】javascript学习 二十四 JavaScript Date(日期)对象
    【Javascript】javascript学习 二十七 JavaScript Math(算数)对象
  • 原文地址:https://www.cnblogs.com/skyflask/p/10398679.html
Copyright © 2011-2022 走看看