5、视图类

一、视图组件之两个视图基类

1、APIView

是DRF提供的视图基类,视图层数据完全由自己写。但这么写有个缺点,就像之前我们学习序列化类里的,有两张表Publish和Book,你写完Book的视图类,还需要写Publish的视图类,和Book的视图类代码差不多,只是里面关联Book表的地方改成Publish......造出了代码冗余。

# 第一层:继承APIView完全自己写
class BookView(APIView):
    def get(self, request):
        qs = Book.objects.all()  # 将查数据库的数据赋值给qs
        ser = serializer.BookSerializer(instance=qs, many=True)  # 序列化查询的数据
        return Response(data=ser.data, status=200)

    def post(self, request):
        ser = serializer.BookSerializer(data=request.data)  # post新增不需要查数据库
        if ser.is_valid():  # 校验数据通过才能保存
            ser.save()
            return Response(data={'code': 100, 'msg': '创建成功'})
        else:  # 不通过则
            return Response(data=ser.errors)

class BookDetailView(APIView):
    def get(self, request, pk):
        book = Book.objects.all().filter(pk=pk).first()
        ser = serializer.BookSerializer(instance=book)
        return Response(data=ser.data, status=200)

    def put(self, request, pk):
        book = Book.objects.all().filter(pk=pk).first()
        ser = serializer.BookSerializer(data=request.data, instance=book)
        if ser.is_valid():
            ser.save()
            return Response(data={'code': 100, 'msg': '修改成功'})
        else:
            return Response(data=ser.errors)

    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()  # 直接删除数据,无需其他操作
        return Response(data={'code': 100, 'msg': '删除成功'})

2、GenericAPIView

这个视图基类继承自APIView,主要增加了操作序列化器和数据库查询的方法,通过GenericAPIView视图基类与视图扩展类,能够解决代码冗余

# 第二层:继承GenericAPIView
'''
1.两个属性
    queryset = Book.objects.all()  # 你要序列化的数据
    serializer_class = serializer.BookSerializer # 你要使用的序列化类
2.三个方法
    get_queryset() # 获取要序列化的数据
    get_serializer() # 获取要使用的序列化类
    get_object()    # 获取单条数据(一定要用pk,如果你想改,重写类属性lookup_field)

'''

from rest_framework.generics import GenericAPIView  # 导入这个模块


class BookView(GenericAPIView): # 继承GenericAPIView
    queryset = Book.objects.all()  # 你要序列化的数据
    serializer_class = serializer.BookSerializer  # 你要使用的序列化类

    def get(self, request):
        qs = self.get_queryset()  # GenericAPIView提供的等同于self.queryset
        ser = self.get_serializer(instance=qs, many=True)  # GenericAPIView提供的等同于self.serializer_class
        return Response(data=ser.data, status=200)

    def post(self, request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(data={'code': 100, 'msg': '创建成功'})
        else:
            return Response(data=ser.errors)


class BookDetailView(GenericAPIView):  
    queryset = Book.objects.all()  # 你要序列化的数据
    serializer_class = serializer.BookSerializer  # 你要使用的序列化类

    def get(self, request, *args, **kwargs):
        book = self.get_object()  # 获取单条
        ser = self.get_serializer(instance=book)
        return Response(data=ser.data, status=200)

    def put(self, request, pk):
        book = self.get_object()
        ser = self.get_serializer(data=request.data, instance=book)
        if ser.is_valid():
            ser.save()
            return Response(data={'code': 100, 'msg': '修改成功'})
        else:
            return Response(data=ser.errors)

    def delete(self, request, pk):
        self.get_object().delete()
        return Response(data={'code': 100, 'msg': '删除成功'})

2-1、五个视图扩展类

提供了对数据增删改查并校验保存的接口,直接使用就行,只能搭配GenericAPIView这种视图基类使用

# 第三层:继承GenericAPIView+5个视图扩展类(不是视图类,没有继承APIView及其子类)
from rest_framework.generics import GenericAPIView
# 导入五个视图扩展类
from rest_framework.mixins import ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, \
    DestroyModelMixin


class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = models.Book.objects.all()  # 你要序列化的数据
    serializer_class = BookSerializer  # 你要使用的序列化类

    def get(self, request):  # get请求查询数据
        return self.list(request)

    def post(self, request):  # post请求增加数据
        return self.create(request)


class BookDeteView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = models.Book.objects.all()  # 你要序列化的数据
    serializer_class = BookSerializer  # 你要使用的序列化类

    def get(self, request, *args, **kwargs):  # 通过主键拿单条数据(或者用*和**也可以)
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):  # put请求修改数据
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):  # delete请求删除数据
        return self.destroy(request, *args, **kwargs)

3、视图组件之9个视图子类

把上面的五个视图扩展类整合,并提供get、pos、put、delete几种方法。(最常使用的视图类)

# 第4层:9个视图子类
from .models import Book
from app01 import serializer
from rest_framework.generics import ListAPIView, CreateAPIView, ListCreateAPIView
from rest_framework.generics import RetrieveAPIView, UpdateAPIView, DestroyAPIView, RetrieveUpdateAPIView, \
    RetrieveDestroyAPIView, RetrieveUpdateDestroyAPIView

# ListAPIView:GenericAPIView + ListModelMixin
# RetrieveUpdateDestroyAPIView:RetrieveModelMixin + UpdateModelMixin + DestroyModelMixin

class BookView(ListCreateAPIView):
    queryset = Book.objects.all()  # 你要序列化的数据
    serializer_class = serializer.BookSerializer  # 你要使用的序列化类


class BookDeteView(RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()  # 你要序列化的数据
    serializer_class = serializer.BookSerializer  # 你要使用的序列化类

4、视图组件之视图集

最简洁!!!直接把五个接口封装到一个类里

# 第5层:继承视图集
from .models import Book
from app01 import serializer
from rest_framework.viewsets import ModelViewSet


class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = serializer.BookSerializer
    
# 由于封装成一个类了,但get请求有两个,所以路由的写法特殊就需要改变一下
path('books/', views.BookView.as_view({'get': 'list', 'post':'create'})),
path('books/<int:pk>', views.BookView.as_view({'get': 'retrieve', 'put':'update', 'update': 'destroy'})),

5、视图集下的其他类

from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet, ViewSet, ViewSetMixin, GenericViewSet

ViewSetMixin  # 可以自定义get,post,delete等方法
ReadOnlyModelViewSet  # 只有查询数据功能,获取所有和单条数据
ViewSet  # APIView + ViewSetMixin
GenericViewSet  # GenericAPIView + ViewSetMixin

# 继承了ViewSet类,可以随意写方法的名字,只需要做好映射
class IndeView(ViewSet):
    def login(self, request):
        return Response('login')
    
   
# url这样写,get请求才能出发执行 视图类的poco方法
path('index/', views.IndeView.as_view({'get': 'login'})),


# 而GenericViewSet就和ViewSet一样啦,但是可以多加GenericAPIView的方法,也就是那两句自动序列化
class IndeView(GenericViewSet):
    queryset = Book.objects.all()  # 你要序列化的数据
    serializer_class = serializer.BookSerializer  # 你要使用的序列化类
    
    def login(self, request):
        return Response('login')

总结:

两大视图基类

APIView:
# DRF提供的视图基类,视图层数据完全由自己写。

GenericAPIView
# 继承自APIView,主要增加了操作序列化器和数据库查询的方法,提供了两个属性三个方法

五个视图扩展类

'''
提供了对数据增删改查并校验保存的接口,直接使用就行,只能搭配GenericAPIView这种视图基类使用。
使用这五个视图扩展类,在继承GenericAPIView的视图类下就不用自己写get、post等方法的具体操作了
'''

ListModelMixin  # 查询所有
CreateModelMixin  # 创建
RetrieveModelMixin  # 单独查询
UpdateModelMixin  # 修改
DestroyModelMixin  # 删除

九个视图子类

'''
把上面的五个视图扩展类和GenericAPIView的整合,并提供get、pos、put、delete几种方法。
直接继承视图子类时,不需要再继承GenericAPIView加某个视图扩展类了,这个是最常使用的视图类
'''    

ListAPIView  # 等于GenericAPIView + ListModelMixin,提供了查询所有数据的功能
CreateAPIView  #  # 等于GenericAPIView + CreateModelMixin,提供了新增数据的功能
ListCreateAPIView  # 将上面两个合并,提供新增+查询所有数据的功能

RetrieveAPIView  # 等于GenericAPIView + RetrieveModelMixin,提供了单独查询数据的功能
UpdateAPIView  # 等于GenericAPIView + UpdateModelMixin,提供了修改数据的功能
DestroyAPIView  # 等于GenericAPIView + DestroyModelMixin,提供了删除数据的功能
RetrieveUpdateAPIView  # 单独查询 + 更新
RetrieveDestroyAPIView  # 单独查询 + 删除
RetrieveUpdateDestroyAPIView  # 等于RetrieveModelMixin + UpdateModelMixin + DestroyModelMixin,单独查询 + 更新 + 删除

视图集

ModelViewSet
# 直接把五个接口封装到一个类里,但因为有两个get(一个获取所有数据、一个获取单条数据),所以路由要特殊写

ViewSetMixin  # 可以自定义get,post,delete等方法
ReadOnlyModelViewSet  # 只有查询数据功能,获取所有和单条数据
ViewSet  # APIView + ViewSetMixin
GenericViewSet  # GenericAPIView + ViewSetMixin
posted @ 2021-09-07 21:54  黑影Poco  阅读(79)  评论(0)    收藏  举报