zoukankan      html  css  js  c++  java
  • drf视图集学习

    1. 五个视图扩展类和GenericAPIView的视图子类: 

    提供了几种后端视图(对数据资源进行曾删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。这五个扩展类需要搭配GenericAPIView父类,因为五个扩展类的实现需要调用GenericAPIView提供的序列化器与数据库查询的方法。

     urls.py

    from django.urls import path, re_path
    from . import views
    
    urlpatterns = [
        path("student/", views.StudentAPIView.as_view()),
        re_path("^student2/(?P<pk>d+)/$", views.Student2APIView.as_view()),
        path("student3/", views.Student3APIView.as_view()),
        re_path("^student4/(?P<pk>d+)/$", views.Student4APIView.as_view()),
    ]

    serializers.py

    from rest_framework import serializers
    from students import models
    
    
    class StudentModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Student
            fields = "__all__"

    views.py

    from .serializers import StudentModelSerializer
    from students import models
    
    from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin
    from rest_framework.generics import GenericAPIView
    
    
    class StudentAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
        serializer_class = StudentModelSerializer
        queryset = models.Student.objects
    
        # 获取多条数据
        def get(self, request):
            return self.list(request)
    
        # 提交数据
        def post(self, request):
            return self.create(request)
    
    
    class Student2APIView(GenericAPIView, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin):
        serializer_class = StudentModelSerializer
        queryset = models.Student.objects
    
        # 修改一条数据
        def post(self, request, pk):
            return self.update(request, pk)
    
        # 查询一条数据
        def get(self, request, pk):
            return self.retrieve(request, pk)
    
        # 删除一条数据
        def delete(self, request, pk):
            return self.destroy(request, pk)
    
    #
    GenericAPIView的视图子类
    from rest_framework.generics import ListAPIView, UpdateAPIView, CreateAPIView, DestroyAPIView, RetrieveAPIView, RetrieveUpdateDestroyAPIView
    
    class Student3APIView(ListAPIView, CreateAPIView):
        serializer_class = StudentModelSerializer
        queryset = models.Student.objects
    
    # class Student4APIView(UpdateAPIView, DestroyAPIView, RetrieveAPIView):
    class Student4APIView(RetrieveUpdateDestroyAPIView):
        serializer_class = StudentModelSerializer
        queryset = models.Student.objects

    2. 视图集Viewset :

    使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:
    list() 提供一组数据
    retrieve() 提供单个数据
    create() 创建数据
    update() 保存数据
    destory() 删除数据
    ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。
    视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上

    视图集GenericViewSet :

    使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,
    所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与`GenericAPIView`,所以还需要继承`GenericAPIView`。 GenericViewSet就帮助我们完成了这样的继承工作,继承自`GenericAPIView`与`ViewSetMixin`,
    在实现了调用as_view()时传入字典(如`{
    'get':'list'}`)的映射处理工作的同时,还提供了`GenericAPIView`提供的基础方法,可以直接搭配Mixin扩展类使用。

    视图集ModelViewSet :

    继承自`GenericViewSet`,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

    ReadOnlyModelViewSet:

    继承自`GenericViewSet`,同时包括了ListModelMixin、RetrieveModelMixin。

    urls.py

    from django.urls import path, re_path
    from . import views
    
    urlpatterns = [
        path("student/", views.StudentAPIViewSet.as_view({"get": "list", "post": "post"})),
        re_path("^student1/(?P<pk>d+)/$",views.StudentAPIViewSet.as_view({"get": "get", "put": "put", "delete": "delete"})),
        path("student2/", views.Student2APIViewSet.as_view({"get": "get", "post": "post"})),
        re_path("^student3/(?P<pk>d+)/$",views.Student2APIViewSet.as_view({"get": "get_one", "put": "put", "delete": "delete"})),
    ]
    
    # 使用路由类给视图集生成路由
    from rest_framework.routers import SimpleRouter, DefaultRouter
    router = DefaultRouter()
    # router.register("路由访问前缀","视图集类","路由别名")
    router.register("student4", views.Student3APIViewSet, )
    print(router.urls)
    # 把路由类生成的路由信息合并到项目中
    urlpatterns += router.urls

    路由说明:

    DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。

    views.py

    from students import models
    from learn.serializers import StudentModelSerializer
    
    from rest_framework.viewsets import ViewSet
    from rest_framework.response import Response
    from rest_framework import status
    
    
    class StudentAPIViewSet(ViewSet):
        def list(self,request):
            """获取多条数据"""
            student_list = models.Student.objects.all()
            serializer = StudentModelSerializer(instance=student_list,many=True)
            return Response(serializer.data)
    
        def post(self,request):
            """添加学生信息"""
            serialzier = StudentModelSerializer(data=request.data)
            serialzier.is_valid(raise_exception=True)
            serialzier.save()
            return Response(serialzier.data)
    
        def get(self,request,pk):
            """获取一条数据"""
            student = models.Student.objects.get(pk=pk)
            serializer = StudentModelSerializer(instance=student)
            return Response(serializer.data)
    
        def put(self,request,pk):
            student = models.Student.objects.get(pk=pk)
            serializer = StudentModelSerializer(instance=student, data=request.data)
            serializer.is_valid(raise_exception=True)
            serializer.save()
            return Response(serializer.data)
    
        def delete(self,request,pk):
            models.Student.objects.get(pk=pk).delete()
            return Response(status=status.HTTP_204_NO_CONTENT)
    
    
    from rest_framework.viewsets import GenericViewSet
    
    
    # GenericViewSet视图集
    class Student2APIViewSet(GenericViewSet):
        serializer_class = StudentModelSerializer
        queryset = models.Student.objects
    
        def get(self,request):
            """获取多条"""
            # serializer = self.serializer_class(instance=self.queryset.all(),many=True)
            serializer = self.get_serializer(instance=self.get_queryset(),many=True)
            return Response(serializer.data)
    
        def post(self,request):
            """添加信息"""
            serialzier = self.get_serializer(data=request.data,context={})
            serialzier.is_valid(raise_exception=True)
            serialzier.save()
            return Response(serialzier.data)
    
        def get_one(self,request,pk):
            """获取一条数据"""
            # serializer = self.serializer_class(instance=self.queryset.get(pk=pk))
            serializer = self.get_serializer(instance=self.get_object())
            return Response(serializer.data)
    
        def put(self,request,pk):
            serializer = self.get_serializer(instance=self.get_object(), data=request.data)
            serializer.is_valid(raise_exception=True)
            serializer.save()
            return Response(serializer.data)
    
        def delete(self,request,pk):
            self.get_object().delete()
            return Response(status=status.HTTP_204_NO_CONTENT)
    
    
    # modelviewset
    from rest_framework.viewsets import ModelViewSet
    from demo.serializers import Studnet2ModelSerializers
    
    
    class Student3APIViewSet(ModelViewSet):
        serializer_class = StudentModelSerializer
        queryset = models.Student.objects
        
        def get_serializer_class(self):
            print(self.action)  # 通过action对象属性来获取当前请求视图集时的action动作是哪个。
            if self.action.lower() == "list":
                return StudentModelSerializer
            else:
                return Studnet2ModelSerializers

    在视图集中自定义动作:

        """
        methods: 设置那些http请求方法能访问到当前视图方法
        detail: 设置生成路由时,是否附带id到地址中
            True:  <URLPattern '^student9/(?P<pk>[^/.]+)/test_api/$' [name='student-test-api']>
            False: <URLPattern '^student9/test_api/$' [name='student-test-api']>
        url_path: 设置访问当前方法的子路由,如果不配置,则默认是是当前方法名
        """
        @action(methods=["get","post"],detail=True)
        def test_api(self,request):
            return Response("测试数据")

     

  • 相关阅读:
    realplayer web播放器控件参数和函数
    几种技术语言简介!
    电子书标志设计,精品设计,形象设计,封面设计,宣传广告设计作品欣赏
    QuickCHM2.6出现了"不支持此接口"
    svchost.exe占用CPU 100%的解决方法
    [转]网站健康检查
    php新帮手 PHPMaker v5.0.1.0
    【OpenGL】理解GL_TRIANGLE_STRIP等绘制三角形序列的三种方式
    UML用例图总结
    【转】Ogre的八叉树场景管理器OctreeSceneManager
  • 原文地址:https://www.cnblogs.com/fdsimin/p/13612037.html
Copyright © 2011-2022 走看看