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("测试数据")

     

  • 相关阅读:
    Scalaz(15)- Monad:依赖注入-Reader besides Cake
    Scalaz(14)- Monad:函数组合-Kleisli to Reader
    Scalaz(13)- Monad:Writer
    Scalaz(12)- Monad:再述述flatMap,顺便了解MonadPlus
    Scalaz(11)- Monad:你存在的意义
    Scalaz(10)- Monad:就是一种函数式编程模式-a design pattern
    Scalaz(9)- typeclass:checking instance abiding the laws
    Scalaz(8)- typeclass:Monoid and Foldable
    Scalaz(7)- typeclass:Applicative-idomatic function application
    Scalaz(6)- typeclass:Functor-just map
  • 原文地址:https://www.cnblogs.com/fdsimin/p/13612037.html
Copyright © 2011-2022 走看看