django-rest-framework-从零开始-6-视图类GenericAPIView的使用

发布时间 2023-03-22 21:11:25作者: 南风丶轻语

django-rest-framework-从零开始-6-视图类GenericAPIView的使用

1、前言

  • 之前提到过的基于APIView类的视图,需要重写["get","post","put","patch", "delete","head","options","trace"]等方法,来达到处理请求的目的。

  • 基于APIView类的视图,核心功能都是一样的,如果我们有多个模型,则需要所有模型都写一个基于APIView类的视图,然后修改其中的模型类和序列化类,这样看起来,代码就重复了很多。

  • 是否有一个类,可以直接完成这些功能,只需要告诉它模型类和序列化类。它就可以自己生成这些方法,并补充完其中的函数体。

2、创建GenericAPIView类视图

上面我们需要一个类,直接完成绑定请求视图的功能。django-rest-framework提供了一些类,可以用于实现以上功能。

改造student_manager/views.py文件

class StudentList(generics.GenericAPIView,
                  mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  ):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer

    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 StudentDetail(generics.GenericAPIView,
                    mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer

    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)

图示

image-20230317111422747

修改student_manager/urls.py路由,指定视图参数pk

re_path(r'detail/(?P<pk>[0-9]+)/', StudentDetail.as_view()),

图示

image-20230317134349455

说明:

  • 我们要基于类的视图,那肯定要继承APIView类,但APIView类无法知道我们的模型类和序列化类都分别是什么,因此django-rest-framework封装了一个类,名叫GenericAPIView类,该类继承了APIView类,因此继承它后,我们也需要定义对应的["get","post","put","patch", "delete","head","options","trace"]方法。

  • GenericAPIView类多了一些方法,能识别模型类和序列化类。我们通过定义GenericAPIView类中querysetserializer_class属性,告知我们的模型类和序列化类。也可以通过重写GenericAPIView类中的get_queryset()get_serializer_class()告知我们的模型类和序列化类

    • 注意:当我们重写了视图类,即重写了["get","post","put","patch", "delete","head","options","trace"]方法,在视图中,如果我们需要获取模型类时,应该调用get_queryset()方法,而不是访问queryset属性,这是drf的约定。

      image-20230317112602261

  • 我们重写了get,post,put,delete方法,这些方法都直接调用了对应mixins文件中的各个基类,完成视图的自动适配。

    • 重写了StudentListget方法,调用了ListModelMixinlist方法,list方法中调用了GenericAPIView类的filter_queryset方法和get_serializer方法,所以最终还是使用了GenericAPIView类和它的基类APIView类的方法。只是绑定了get请求来临时,调用list方法。

    • 重写的post方法,调用了CreateModelMixin类的create方法,create方法中调用了GenericAPIView类的get_serializer方法,最终调用了序列化类的save方法,save方法,还是调用序列化类的create方法(这是之前就了解到的了)。

    • 重写了StudentDetail中的get方法,调用了RetrieveModelMixinretrieve方法,retrieve方法调用了GenericAPIView类的get_object()get_serializer方法

    • 重写了put方法,调用了UpdateModelMixin的update方法,update方法调用了GenericAPIView类的get_object()get_serializer方法以及最终调用了序列化类的save方法,save方法,还是调用序列化类的create方法(这是之前就了解到的了)。

    • 重写了delete方法,调用了DestroyModelMixindestory方法,destory方法调用了GenericAPIView类的get_object()最终调用了模型类的delete方法

      大概就是表中样子,具体可以看源码

      视图方法 对应视图基类及方法 调用GenericAPIView类的函数
      List中的get方法 ListModelMixin:list() get_queryset()和get_serializer()
      post CreateModelMixin:create() get_serializer()
      Detail的get方法 RetrieveModelMixin:retrieve() get_object()和get_serializer()
      put UpdateModelMixin:update() get_object()和get_serializer()
      delete DestroyModelMixin:destory() get_object()
  • 这里要注意的是,URL路由的写法,需要为(?Ppattern) 这种写法

3、启动服务,测试基于GenericAPIView类视图

测试和之前一样。

github:https://github.com/rainbow-tan/learn-drf