视图组件

1 两个视图基类

1.1 APIView

from rest_framework.views import APIView

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

  基于APIView写接口

# views.py
from rest_framework.views import APIView
from app01.models import Book
from app01.ser import BookSerializer
# 基于APIView写的
class BookView(APIView):
    def get(self,request):
        book_list=Book.objects.all()
        book_ser=BookSerializer(book_list,many=True)

        return Response(book_ser.data)
    def post(self,request):
        book_ser = BookSerializer(data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.data)
        else:
            return Response({'status':101,'msg':'校验失败'})


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

    def put(self, request,pk):
        book = Book.objects.all().filter(pk=pk).first()
        book_ser = BookSerializer(instance=book,data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.data)
        else:
            return Response({'status': 101, 'msg': '校验失败'})

    def delete(self,request,pk):
        ret=Book.objects.filter(pk=pk).delete()
        return Response({'status': 100, 'msg': '删除成功'})
    
#models.py
class Book(models.Model):
    name=models.CharField(max_length=32)
    price=models.DecimalField(max_digits=5,decimal_places=2)
    publish=models.CharField(max_length=32)

#ser.py
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model=Book
        fields='__all__'

# urls.py
path('books/', views.BookView.as_view()),
re_path('books/(?P<pk>d+)', views.BookDetailView.as_view()),
APIView写接口

1.2 GenericAPIView[通用视图类]

form rest_framework.generics import GenericAPIView

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

  提供的关于序列化器使用的属性与方法

  • 属性:

    • serializer_class 指明视图使用的序列化器
  • 方法:

    • get_serializer_class(self)

      当出现一个视图类中调用多个序列化器时,那么可以通过条件判断在get_serializer_class方法中通过返回不同的序列化器类名就可以让视图方法执行不同的序列化器对象了。

      返回序列化器类,默认返回serializer_class

    • get_serializer(self, args, *kwargs)

      返回序列化器对象,主要用来提供给Mixin扩展类使用,如果我们在视图中想要获取序列化器对象,也可以直接调用此方法。

      注意,该方法在提供序列化器对象的时候,会向序列化器对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。

      • request 当前视图的请求对象
      • view 当前请求的类视图对象
      • format 当前请求期望返回的数据格式

  

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

  • 属性:

    • queryset 指明使用的数据查询集
  • 方法:

    • get_queryset(self)

      返回视图使用的查询集,主要用来提供给Mixin扩展类使用,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以重写

    • get_object(self)

      返回详情视图所需的模型类数据对象,主要用来提供给Mixin扩展类使用。

      在试图中可以调用该方法获取详情信息的模型类对象。

      若详情访问的模型类对象不存在,会返回404。

      该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。

  

  其他可以设置的属性

  • pagination_class 指明分页控制类
  • filter_backends 指明过滤控制后端  

  基于GenericAPIView写接口 

# views.py
class Book2View(GenericAPIView):
    #queryset要传queryset对象,查询了所有的图书
    # serializer_class使用哪个序列化类来序列化这堆数据
    queryset=Book.objects
    # queryset=Book.objects.all()
    serializer_class = BookSerializer
    def get(self,request):
        book_list=self.get_queryset()
        book_ser=self.get_serializer(book_list,many=True)

        return Response(book_ser.data)
    def post(self,request):
        book_ser = self.get_serializer(data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.data)
        else:
            return Response({'status':101,'msg':'校验失败'})


class Book2DetailView(GenericAPIView):
    queryset = Book.objects
    serializer_class = BookSerializer
    def get(self, request,pk):
        book = self.get_object()
        book_ser = self.get_serializer(book)
        return Response(book_ser.data)

    def put(self, request,pk):
        book = self.get_object()
        book_ser = self.get_serializer(instance=book,data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.data)
        else:
            return Response({'status': 101, 'msg': '校验失败'})

    def delete(self,request,pk):
        ret=self.get_object().delete()
        return Response({'status': 100, 'msg': '删除成功'})
    
 #url.py
    # 使用GenericAPIView重写的
    path('books2/', views.Book2View.as_view()),
    re_path('books2/(?P<pk>d+)', views.Book2DetailView.as_view()),
基于GenericAPIView写的接口

2 基于GenericAPIView的五个视图扩展类

from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin

  作用:

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

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

2.1 ListModelMixin

  列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。(查询所有数据)

2.2 CreateModelMixin

  创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。

  如果序列化器对前端发送的数据验证失败,返回400错误。(新建一个数据)

2.3 RetrieveModelMixin

  详情视图扩展类,提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。

  如果存在,返回200, 否则返回404。(查询一条数据)

2.4 UpdateModelMixin

  更新视图扩展类,提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。

  同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。

  成功返回200,序列化器校验数据失败时,返回400错误。(更新数据)

2.5 DestroyModelMixin

  删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。

  成功返回204,不存在返回404。(删除一条数据)

基于GenericAPIView和5个视图扩展类写的接口

from rest_framework.mixins import  ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin
# views.py
class Book3View(GenericAPIView,ListModelMixin,CreateModelMixin):

    queryset=Book.objects
    serializer_class = BookSerializer
    def get(self,request):
        return self.list(request)

    def post(self,request):
        return self.create(request)

class Book3DetailView(GenericAPIView,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin):
    queryset = Book.objects
    serializer_class = BookSerializer
    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)
# urls.py
    # 使用GenericAPIView+5 个视图扩展类  重写的
    path('books3/', views.Book3View.as_view()),
    re_path('books3/(?P<pk>d+)', views.Book3DetailView.as_view()),
基于GenericAPIView和5个视图扩展类写的接口

3 GenericAPIView的7个视图子类

  实际有9个我只写了7个,剩下2个也能猜出来

from rest_framework.generics import xxxAPIView

3.1 CreateAPIView

  提供 post 方法

  继承自: GenericAPIView、CreateModelMixin

3.2 ListAPIView

  提供 get 方法

  继承自:GenericAPIView、ListModelMixin

3.3 RetrieveAPIView

  提供 get 方法

  继承自: GenericAPIView、RetrieveModelMixin

3.4 DestoryAPIView

  提供 delete 方法

  继承自:GenericAPIView、DestoryModelMixin

3.5 UpdateAPIView

  提供 put 和 patch 方法

  继承自:GenericAPIView、UpdateModelMixin

3.6 RetrieveUpdateAPIView

  提供 get、put、patch方法

  继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin

3.7 RetrieveUpdateDestoryAPIView

  提供 get、put、patch、delete方法

  继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin

4 视图集ViewSet

  上面的方法写接口时都要写get(),post()等....使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:

  ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。

  视图集有:

4.1 使用ModelViewSet来写上面的几个接口

# views.py
from rest_framework.viewsets import ModelViewSet
class Book5View(ModelViewSet):  #5个接口都有,但是路由有点问题
    queryset = Book.objects
    serializer_class = BookSerializer
    
# urls.py
# 使用ModelViewSet编写5个接口
    path('books5/', views.Book5View.as_view(actions={'get':'list','post':'create'})), #当路径匹配,又是get请求,会执行Book5View的list方法
    re_path('books5/(?P<pk>d+)', views.Book5View.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})),

 4.2 源码分析ViewSetMixin

# 重写了as_view
# 核心代码(所以路由中只要配置了对应关系,比如{'get':'list'}),当get请求来,就会执行list方法
for method, action in actions.items():
    #method:get
    # action:list
    handler = getattr(self, action)
    #执行完上一句,handler就变成了list的内存地址
    setattr(self, method, handler)
    #执行完上一句  对象.get=list
    #for循环执行完毕 对象.get:对着list   对象.post:对着create

4.3 继承ViewSetMixin的视图类

# views.py
from rest_framework.viewsets import ViewSetMixin
class Book6View(ViewSetMixin,APIView): #一定要放在APIVIew前
    def get_all_book(self,request):
        print("xxxx")
        book_list = Book.objects.all()
        book_ser = BookSerializer(book_list, many=True)
        return Response(book_ser.data)
    
# urls.py
    #继承ViewSetMixin的视图类,路由可以改写成这样
    path('books6/', views.Book6View.as_view(actions={'get': 'get_all_book'})),

5 补充

5.1 在pycharm中查看类的继承关系

5.2 上述几个视图类的继承关系

  两个基类:

    APIView:继承了View

    GenericView:继承了APIView

  五个视图扩展类:rest_framework.mixins      要和GenericView搭配使用     全都继承object

CreateModelMixin:create方法创建一条
DestroyModelMixin:destory方法删除一条
ListModelMixin:list方法获取所有
RetrieveModelMixin:retrieve获取一条
UpdateModelMixin:update修改一条

  九个视图的子类:rest_framework.generics    

下面的9个全部继承了GenericView
CreateAPIView:继承CreateModelMixin   有put方法(create)新增数据
DestroyAPIView:继承DestroyModelMixin  有delete方法(destory)删除数据
ListAPIView:继承ListModelMixin   有get方法(list)获取所有
UpdateAPIView:继承UpdateModelMixin    有put方法(updata)修改数据
RetrieveAPIView:继承RetrieveModelMixin   有get方法(retrieve)查询1条数据


ListCreateAPIView:继承ListModelMixin,CreateModelMixin   有get,put方法(list,create)获取所有,新增数据
RetrieveDestroyAPIView:继承RetrieveModelMixin,DestroyModelMixin   有get,delete方法(retrieve,destory)查1条和删除
RetrieveUpdateAPIView:继承RetrieveModelMixin,UpdateModelMixin 有get,put方法(retrieve,updata)查1条和更新
RetrieveUpdateDestroyAPIView:继承RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin  有get,put,delete方法(retrieve,updata,destory)查1条,更新,删除数据
原文地址:https://www.cnblogs.com/bk134/p/13267657.html