drf-视图组件

发布时间 2023-09-04 18:45:31作者: Maverick-Lucky

一、视图

Django REST framwork 提供的视图的主要作用:

  • 控制序列化器的执行(检验、保存、转换数据)
  • 控制数据库查询的执行

REST framework 提供了众多的通用视图基类与扩展类,以简化视图的编写。

1.  两个视图基类

1.1 APIView

from rest_framework.views import APIView

APIView是REST framework提供的所有视图的基类,继承自Django的View父类

APIViewView的不同之处在于:

  • 传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
  • 视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
  • 任何APIException异常都会被捕获到,并且处理成合适的响应信息;
  • 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。

APIView中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法。

###### 第一层: 继承APIView编写book5个接口
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer
from .models import Book


class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        ser = BookSerializer(instance=book_list, many=True)
        return Response(ser.data)

    def post(self, request):
        ser = BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()  # 反序列化保存
            return Response(ser.data)  # 创建成功后,返回创建后的对象, 做了个序列化
        else:
            return Response(ser.errors)
class BookDetailView(APIView):
    def get(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book)
        return Response(ser.data)

    def put(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)

    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()
        return Response('')

1.2 GenericAPIView[通用视图类]

from rest_framework.generics import GenericAPIView

  继承了APIVIew,主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持。通常在使用时,可搭配一个或多个Mixin扩展类。

提供的关于数据库查询的属性与方法

    • 重要属性:

      • queryset : 以后放所有某个表查询出的数据
      • Serializer_class : 要序列化的类
      • get_object  :修改,查询的单条
    • 了解类属性:

      • lookup_field = 'pk'  路由使用转换器,转换出来的参数,查询单条要用到,如果改了,路由对应也要修改,一般不改

      • filter_backends:后面详细讲     过滤 功能
      • pagination_class :后面详细讲  分页
         
    • 了解方法:

      • get_serializer_class  后期咱们可能会重写它,指定某些方法使用不同的序列化类

      • filter_queryset 后面跟过滤功能一起讲

代码:

from rest_framework.generics import GenericAPIView

from .models import Publish
from .serializer import PublishSerializer
class PublishView(GenericAPIView):
    # 本次视图类中要操作的数据
    queryset = Publish.objects.all()  # 类只要加载,就会执行,查了所有数据,不能以它为准
    # 本次视图类中要调用的默认序列化器
    serializer_class = PublishSerializer

    def get(self, request):
        # 获取所有的出版社数据
        obj_list = self.get_queryset()  # 以用的时候为准
        # 使用对应的序列化类进行处理数据
        ser = self.get_serializer(instance=obj_list, many=True)
        return Response(ser.data)

    def post(self, request):
       # 使用对应的序列化类进行处理数据
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()  # 反序列化保存
            return Response(ser.data)  # 创建成功后,返回创建后的对象, 做了个序列化
        else:
            return Response(ser.errors)


class PublishDetailView(GenericAPIView):
    serializer_class = PublishSerializer # 要给这两个参数传对应的值
    queryset = Publish.objects.all()
     
    def get(self, request, pk):
        # 查询对应PK的那条数据
        obj = self.get_object()
        ser = self.get_serializer(instance=obj)
        return Response(ser.data)

    def put(self, request, pk):
        obj = self.get_object()
        ser = self.get_serializer(instance=obj, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)

    def delete(self, request, pk):
        self.get_object().delete()
        return Response('')        

对应的序列化类:

class PublishSerializer(serializers.ModelSerializer):
    class Meta:
        model=Publish
        fields='__all__'

总结:

  # 易犯的错误1:一定要在用数据的时候再查

    def get_queryset(self):

      return self.queryset.all()

  #  错误2:咱么没有在类属性上配置 queryset这个参数--->源码中做了断言

1.2 5个视图扩展类

作用:

提供了几种后端视图(对数据资源进行曾删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。

这五个扩展类需要搭配GenericAPIView父类,因为五个扩展类的实现需要调用GenericAPIView提供的序列化器与数据库查询的方法。

RetrieveModelMixin, 查询一条,写了一个方法 retrieve---》代码就是 跟咱们之前写获取单条get方法内容一样

CreateModelMixin 新增一条写了一个方法 create---》代码就是 跟咱们之前写新增一条 post 方法内容一样

DestroyModelMixin,删除一条写了一个方法 destroy---》代码就是 跟咱们之前写删除一条 delete 方法内容一样

ListModelMixin,查询所有写了一个方法 list---》代码就是 跟咱们之前写删除一条 get 方法内容一样

UpdateModelMixin 修改一个写了一个方法 update---》代码就是 跟咱们之前写删除一条put 方法内容一样

为什么要写5个视图扩展类,不写俩?

  因为后期不一定 5个接口都写

代码:

class PublishView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = Publish.objects.all()  # 类只要加载,就会执行,查了所有数据,不能以它为准
    serializer_class = PublishSerializer

    def get(self, request):
        return self.list(request)

    def post(self, request):
        # return  self.create(request) # 一定不要忘了return
        return super().create(request)  # 一定不要忘了return


class PublishDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    serializer_class = PublishSerializer
    queryset = Publish.objects.all()

    def get(self, request, pk):
        return self.retrieve(request, pk)

    def put(self, request, pk):
        return self.update(request, pk)

    def delete(self, request, pk):
        return self.destroy(request, pk)