zoukankan      html  css  js  c++  java
  • [Python自学] DRF (2) (视图类的封装)

    参考博客:https://www.cnblogs.com/yuanchenqi/articles/8719520.html

    一、mixins模块(level-1)

    1.需要解决的问题

    在 [Python自学] restframework 中,我们实现了publish和book的增删改查(包括单条查询,一共5个视图操作)。

    但是如果我们还有很多同样需要实现5种操作的实例种类,那么代码重复量会非常大。如何解决这个问题,restframework已经为我们提供了解决方法。

    2.mixins模块

    restframework为我们提供了mixins模块:

    from rest_framwork import mixins

    mixins模块中为我们提供了5个类:

    mixins.ListModelMixin  # 获取全量数据(对应get)
    mixins.CreateModelMixin  # 插入数据(对应post)
    mixins.UpdateModelMixin  # 更新数据(对应put)
    mixins.DestroyModelMixin  # 删除数据(对应delete)
    mixins.RetrieveModelMixin  # 获取单条数据(对应get)

    3.authors对应的两个视图类

    from rest_framework import mixins
    from rest_framework import generics
    
    
    class AuthorView(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):
        pass
    
    
    class AuthorDetailView(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin,
                         generics.GenericAPIView):
        pass

    AuthorView中主要做全量获取和创建一条数据,所以继承ListModelMixin和CreateModelMixin。

    GenericAPIView继承自APIView,是使用Mixins的基础。

    例如,在AuthorView中,他继承了ListModelMixin类,则相当于自己有了一个叫list的方法(这个list方法就相当于get视图方法),继承了CreateModelMixin类,相当于自己有了一个create的方法(相当于post视图方法),继承了GnericAPIView相当于继承了APIView类。

    Authors对应的urls路由条目:

    from django.contrib import admin
    from django.urls import path, re_path
    from demo import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path('^publishes/$', views.PublishView.as_view(), name="publish"),
        re_path('^publishes/(?P<pk>d+)/$', views.PublishDetailView.as_view(), name="publishdetail"),
        re_path('^books/$', views.BookView.as_view(), name="book"),
        re_path('^books/(?P<pk>d+)/$', views.BookDetailView.as_view(), name="bookdetail"),
        re_path('^authors/$', views.AuthorView.as_view(), name="author"),
        re_path('^authors/(?P<pk>d+)/$', views.AuthorDetailView.as_view(), name="authordetail"),
    ]

    4.实现AuthorView类

    from rest_framework import mixins
    from rest_framework import generics
    from .models import Author
    
    
    # Author序列化类
    class AuthorModelSerializers(serializers.ModelSerializer):
        class Meta:
            model = Author
            fields = "__all__"
    
    
    class AuthorView(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):
        queryset = Author.objects.all()
        serializer_class = AuthorModelSerializers
    
        # 获取全部authors
        def get(self, request, *args, **kwargs):
            return self.list(request, *args, **kwargs)
    
        # 插入一条数据
        def post(self, request, *args, **kwargs):
            return self.create(request, *args, **kwargs)

    5.实现AuthorDetailView类

    class AuthorDetailView(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin,
                           generics.GenericAPIView):
        queryset = Author.objects.all()
        serializer_class = AuthorModelSerializers
    
        # 获取单条author记录
        def get(self, request, *args, **kwargs):
            return self.retrieve(request, *args, **kwargs)
    
        # 更新一条记录
        def put(self, request, *args, **kwargs):
            return self.update(request, *args, **kwargs)
    
        # 删除一条记录
        def delete(self, request, *args, **kwargs):
            return self.destroy(request, *args, **kwargs)

    6.测试结果

    获取全量数据:

    Postman以get请求访问http://127.0.0.1:8000/authors/:

    [
        {
            "id": 1,
            "name": "leo",
            "age": 32
        },
        {
            "id": 2,
            "name": "alex",
            "age": 35
        },
        {
            "id": 3,
            "name": "Jone",
            "age": 23
        },
        {
            "id": 4,
            "name": "Lucy",
            "age": 30
        }
    ]

    插入一条数据:

    Postman以post请求访问http://127.0.0.1:8000/authors/,post数据:

    {
        "name": "李雷",
        "age": 90
    }

    成功返回以上数据,再查询全量数据:

    [
        {
            "id": 1,
            "name": "leo",
            "age": 32
        },
        {
            "id": 2,
            "name": "alex",
            "age": 35
        },
        {
            "id": 3,
            "name": "Jone",
            "age": 23
        },
        {
            "id": 4,
            "name": "Lucy",
            "age": 30
        },
        {
            "id": 5,
            "name": "李雷",
            "age": 90
        }
    ]

    成功插入数据。

    获取一条数据:

    Postman发送get请求,http://127.0.0.1:8000/authors/4/:

    返回数据:

    {
        "id": 4,
        "name": "Lucy",
        "age": 30
    }

    修改一条数据:

    将id为4的author的年龄修改为33,向http://127.0.0.1:8000/authors/4/发送put请求,数据如下:

    {
        "name": "Lucy",
        "age": 33
    }

    成功返回以上数据,再次查询id为4的author的信息:

    {
        "id": 4,
        "name": "Lucy",
        "age": 33
    }

    年龄修改成功。

    删除一条数据:

    删除id为4的数据,发送delete请求到http://127.0.0.1:8000/authors/4/。

    返回空值。

    查看全量数据:

    [
        {
            "id": 1,
            "name": "leo",
            "age": 32
        },
        {
            "id": 2,
            "name": "alex",
            "age": 35
        },
        {
            "id": 3,
            "name": "Jone",
            "age": 23
        },
        {
            "id": 5,
            "name": "李雷",
            "age": 90
        }
    ]

    成功删除id为4的数据。

    二、generic模块(level-2)

    除了第一节中使用的mixins模块,在generic模块中还对mixins的使用进行了封装,AuthorView和AuthorDetailView还可以变成如下形式:

    1.generic中封装的类

    # 单独封装
    generics.ListAPIView
    generics.CreateAPIView
    generics.RetrieveAPIView
    generics.UpdateAPIView
    generics.DestroyAPIView
    
    # 两个操作组合封装
    generics.ListCreateAPIView
    generics.RetrieveUpdateAPIView
    generics.RetrieveDestroyAPIView
    
    # 三个操作组合封装
    generics.RetrieveUpdateDestroyAPIView

    generic将我们可以在视图类中用要的方法全部封装在一起,我们只需要继承就可以了,get、post、put、delete等方法都被封装在其中了。

    2.使用这些类

    from rest_framework import generics
    from .models import Author
    
    
    # Author序列化类
    class AuthorModelSerializers(serializers.ModelSerializer):
        class Meta:
            model = Author
            fields = "__all__"
    
    
    class AuthorView(generics.ListCreateAPIView):
        queryset = Author.objects.all()
        serializer_class = AuthorModelSerializers
    
    
    class AuthorDetailView(generics.RetrieveUpdateDestroyAPIView):
        queryset = Author.objects.all()
        serializer_class = AuthorModelSerializers

    如上述代码所示,代码变得更加简洁了。我们只需要控制数据源(queryset)以及显示格式(serializer_class)即可。

    三、viewsets模块(level-3)

    我们可以将AuthorView和AuthorDetailView合并成一个类,能够执行5种操作。

    from .models import Author
    from rest_framework import viewsets
    
    
    # Author序列化类
    class AuthorModelSerializers(serializers.ModelSerializer):
        class Meta:
            model = Author
            fields = "__all__"
    
    
    class AuthorViewSet(viewsets.ModelViewSet):
        queryset = Author.objects.all()
        serializer_class = AuthorModelSerializers

    对应urls路由条目修改为:

    from django.contrib import admin
    from django.urls import path, re_path
    from demo import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path('^publishes/$', views.PublishView.as_view(), name="publish"),
        re_path('^publishes/(?P<pk>d+)/$', views.PublishDetailView.as_view(), name="publishdetail"),
        re_path('^books/$', views.BookView.as_view(), name="book"),
        re_path('^books/(?P<pk>d+)/$', views.BookDetailView.as_view(), name="bookdetail"),
        re_path('^authors/$', views.AuthorViewSet.as_view({"get": "list", "post": "create"}), name="author"),
        re_path('^authors/(?P<pk>d+)/$', views.AuthorViewSet.as_view(
            {"get": "retrieve", "put": "update", "patch": "partial_update", "delete": "destroy"}), name="authordetail"),
    ]

    还是两个url路由条目,但是指向的是同一个视图类,不同的是视图函数对应的成员方法不同,用字典参数进行映射。

    这里最关键的就是as_view()方法的参数。

    这里的as_view()是AuthorViewSet中的as_view(),该方法在 ViewSetMixin 类中实现的,该方法对参数进行了处理。

    而前面的PublishView等类的as_view()是在APIView类中实现的,是没有对参数进行处理的。

    (>‿◠)✌

  • 相关阅读:
    CentOS 6.5系统使用yum方式安装LAMP环境
    省市区三级联动—PCASClass
    javascript进击(九)参考手册
    javascript进击(八)JSON
    javascript进击(七)Ajax
    javascript进击(六)Jquery
    javascript进击(五)JS对象
    javascript进击(四)HTML DOM
    javascript进击(三)简介
    javascript进击(一)简介
  • 原文地址:https://www.cnblogs.com/leokale-zz/p/12234348.html
Copyright © 2011-2022 走看看