drf05 视图

一、视图

1. 介绍

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

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

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

2. 前期准备

# models.py 
from django.db import models

class Book(models.Model):
    name=models.CharField(max_length=32)
    price=models.DecimalField(max_digits=5,decimal_places=2)
    
    
# ser.py
from rest_framework import serializers
from app03_views import models

class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = '__all__'
        extra_kwargs ={
            'id':{'read_only':True}
        }

3. 视图

2.1 两个视图基类

2.1.1 APIView(drf 所有视图基类)

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

APIViewView的不同之处在于:

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

支持定义的类属性

  • authentication_classes 列表或元祖,身份认证类
  • permissoin_classes 列表或元祖,权限检查类
  • throttle_classes 列表或元祖,流量控制类

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

编写五个接口(使用)
路由层
# urls.py
from django.urls import path, re_path
from app03_views import views

urlpatterns = [
    # APIView
    # 增、删、改、查
    path('books/', views.BooksAPIView.as_view()),
    re_path(r'^books/(?P<pk>\d+)/', views.BookAPIView.as_view()),

]
视图层
from django.shortcuts import render
# Create your views here.
from rest_framework.views import APIView
from rest_framework.response import Response
from app03_views.ser import BookSerializers
from app03_views import models
# response 相关
from rest_framework.renderers import JSONRenderer # 用来配置response的返回方式
from rest_framework.renderers import BrowsableAPIRenderer
from rest_framework import status
# APIView + 序列化
class BookAPIView(APIView):
    # 获取单条数据
    def get(self, request, pk):
        print('get-pk')
        obj = models.Book.objects.filter(pk=pk).first()
        ser = BookSerializers(instance=obj, )
        if obj:
            return Response(ser.data)
        else:
            return Response(ser.errors)
	# 修改单条数据
    def put(self, request, pk):
        print('put-pk')
        obj = models.Book.objects.filter(pk=pk).first()
        ser = BookSerializers(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):
        print('delete-pk')
        obj = models.Book.objects.filter(pk=pk)
        if obj:
            obj.delete()
            return Response(status=status.HTTP_200_OK)
        else:
            return Response(status=status.HTTP_406_NOT_ACCEPTABLE)


class BooksAPIView(APIView):
    # 获取所有数据
    def get(self, request):
        obj = models.Book.objects.all()
        ser = BookSerializers(instance=obj, many=True)
        if obj:
            return Response(ser.data)
        else:
            return Response(ser.errors)
    # 新建单条数据
    def post(self, request):
        ser = BookSerializers(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)

2.1.2 GenericAPIView[通用视图类]

问题与解决

问题:APIView 重写了django的view 方法后,使用还和以前一样,只是封装了request和response方法

​ 但是,每次在写5个接口方法的时候,每次都要调用 模型类和序列化器类方法,

​ 并且,遇到个新的模型类,就需要对代码进行重写一遍,比较耗费时间

解决: GenericAPIView 基础APIView 类 ,将模型类和序列化器类进行封装,

​ 这时,无论是哪个模型,改掉 前面的 模型对象 和序列化器类 就可以很快的实现多个接口类

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

属性
# 属性
# 常用属性
 queryset = models.Book.objects.all()     # 传入queryset对象
 serializer_class = BookSerializers # 序列化类

# 其它属性
 lookup_field = 'pk'                # 查询字段 - 设置单个
 ookup_url_kwarg = None             # 查询字段 - 设置多个
方法
# 方法
# 常用方法
get_object()     # 返回一个对象,适用于单条数据
get_queryset()   # 返回queryset对象,适用于多条数据
get_serializer(self, *args, **kwargs) # 用法同普通序列化,多条数据,要加 many=True

# 其它方法
get_serializer_class(self)   # 当试图中使用多个序列化器类时,可以使用该方法来区分
# 案例
 def get_serializer_class(self):
        print('111111111111')
        if self.request.method == 'GET':
            return StudentModelSerializer2
      else:
            return StudentModelSerializer
编写五个接口(使用)

上述的是个整体属性和参数的介绍,这里我们就用最基本也是最常见的方法来编写

另外,指出的是,GenericAPIView类 是继承APIView类 拥有其所有的功能

在此基础上新增了序列化的通用处理

路由层
from django.urls import path, re_path, include
from app03_views import views

urlpatterns = [

    # GenericAPIView
    # 增、删、改、查
    path('books2/', views.BooksGenericAPIView.as_view()),
    re_path(r'^books2/(?P<pk>\d+)/', views.BookGenericAPIView.as_view()),]
视图层
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from app03_views.ser import BookSerializers
from app03_views import models
# response 相关
from rest_framework.renderers import JSONRenderer # 用来配置response的返回方式
from rest_framework.renderers import BrowsableAPIRenderer
from rest_framework import status


# GenericAPIView + 序列化
class BookGenericAPIView(GenericAPIView):

    queryset = models.Book.objects.all()   # 传入queryset对象
    serializer_class = BookSerializers # 序列化类
    lookup_field = 'pk'     # 查询字段 - 设置单个
    lookup_url_kwarg = None # 查询字段 - 设置多个

    def get(self, request, pk):
        print('get-pk')
        # obj = models.Book.objects.filter(pk=pk).first()
        # ser = BookSerializers(instance=obj, )
        obj = self.get_object()
        ser = self.get_serializer(obj)

        if obj:
            return Response(ser.data)
        else:
            return Response(ser.errors)

    def put(self, request, pk):
        print('put-pk')
        # obj = models.Book.objects.filter(pk=pk).first()
        # ser = BookSerializers(instance=obj, data=request.data)
        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):
        print('delete-pk')
        # obj = models.Book.objects.filter(pk=pk)
        obj = self.get_object()
        if obj:
            obj.delete()
            return Response(status=status.HTTP_200_OK)
        else:
            return Response(status=status.HTTP_406_NOT_ACCEPTABLE)


class BooksGenericAPIView(GenericAPIView):
    queryset = models.Book.objects.all()   # 传入queryset对象
    serializer_class = BookSerializers # 序列化类
    lookup_field = 'pk'     # 查询字段 - 设置单个
    lookup_url_kwarg = None # 查询字段 - 设置多个

    def get(self, request):
        # obj = models.Book.objects.all()
        # ser = BookSerializers(instance=obj, many=True)
        obj = self.get_queryset()
        ser = self.get_serializer(instance=obj, many=True)
        if obj:
            return Response(ser.data)
        else:
            return Response(ser.errors)

    def post(self, request):
        # ser = BookSerializers(data=request.data)
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)

2.2 五个视图扩展类

问题与解决:

问题:虽然GenericAPIView 封装了序列化方法,可以快速编写多个模型类

​ 但是,相关的五个接口还需要自己去书写

解决:继承GenericAPIView ,并对五个接口的方法进行封装,需要哪个接口直接调用即可

​ 这是,需要哪个接口,只要继承它就能实现功能,不需要写其它代码

作用:

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

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

(1)ListModelMixin

获取多条数据的 列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。

该Mixin的list方法会对数据进行过滤和分页。

源代码:

class ListModelMixin(object):
    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        # 过滤
        queryset = self.filter_queryset(self.get_queryset())
        # 分页
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        # 序列化
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

举例:

from rest_framework.mixins import ListModelMixin

class BookListView(ListModelMixin, GenericAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

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

(2)CreateModelMixin

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

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

源代码:

class CreateModelMixin(object):
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        # 获取序列化器
        serializer = self.get_serializer(data=request.data)
        # 验证
        serializer.is_valid(raise_exception=True)
        # 保存
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}

示例:

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

(3)RetrieveModelMixin

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

如果存在,返回200, 否则返回404。

源代码:

class RetrieveModelMixin(object):
    """
    Retrieve a model instance.
    """
    def retrieve(self, request, *args, **kwargs):
        # 获取对象,会检查对象的权限
        instance = self.get_object()
        # 序列化
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

举例:

class BookDetailView(RetrieveModelMixin, GenericAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    def get(self, request, pk):
        return self.retrieve(request,pk)
        return self.retrieve(request) #pk也可以不传

(4)UpdateModelMixin

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

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

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

源代码:

class UpdateModelMixin(object):
    """
    Update a model instance.
    """
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        return Response(serializer.data)

    def perform_update(self, serializer):
        serializer.save()

    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)

示例:

def put(self,request,pk):
  """更新一条数据"""
  return self.update(request,pk)

(5)DestroyModelMixin

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

成功返回204,不存在返回404。

源代码:

class DestroyModelMixin(object):
    """
    Destroy a model instance.
    """
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def perform_destroy(self, instance):
        instance.delete()

示例:

def delete(self,request,pk):
        """删除一条数据"""
        return self.destroy(request,pk)

编写五个接口(使用)

重点:GenericAPIView 一定要放在最前面
路由层
from django.contrib import admin
from django.urls import path, re_path, include
from app03_views import views

urlpatterns = [
    # GenericAPIView + 五个扩展类
    # 增、删、改、查
    path('books3/', views.BooksGenericAPIViewMixin.as_view()),
    re_path(r'^books3/(?P<pk>\d+)/', views.BookGenericAPIViewMixin.as_view()),]
视图层
# GenericAPIView + 五个扩展类
class BookGenericAPIViewMixin(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):

    queryset = models.Book.objects.all()   # 传入queryset对象
    serializer_class = BookSerializers # 序列化类
    lookup_field = 'pk'     # 查询字段 - 设置单个
    lookup_url_kwarg = None # 查询字段 - 设置多个

    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)

# GenericAPIView + 五个扩展类
class BooksGenericAPIViewMixin(GenericAPIView,ListModelMixin,CreateModelMixin):
    queryset = models.Book.objects.all()  # 传入queryset对象
    serializer_class = BookSerializers # 序列化类
    lookup_field = 'pk'     # 查询字段 - 设置单个
    lookup_url_kwarg = None # 查询字段 - 设置多个

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

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

2.3 九个GenericAPIView的视图子类

模块导入

from rest_framework.generics import ListAPIView, CreateAPIView
from rest_framework.generics import RetrieveAPIView, UpdateAPIView, DestroyAPIView
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
from rest_framework.generics import RetrieveDestroyAPIView,RetrieveUpdateAPIView
(1) CreateAPIView
#提供 post 方法 -all

# 继承自: GenericAPIView、CreateModelMixin
(2) ListAPIView
#提供 get方法 -all

# 继承自: GenericAPIView、ListModelMixin
(3) RetrieveAPIView
# 提供 get方法 -pk

# 继承自: GenericAPIView、RetrieveModelMixin
(4) UpdateAPIView
# 提供 put - pk

# 继承自: GenericAPIView、UpdateModelMixin
(5) DestoryAPIView
# 提供 delete - pk

# 继承自: GenericAPIView、DestroyModelMixin
(6) ListCreateAPIView
# 提供 get方法 - post方法 -all

# 继承自: GenericAPIView、CreateModelMixin、ListModelMixin
(7) RetrieveUpdateDestoryAPIView
# 提供 get/put/delete -pk

# 继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestroyModelMixin
(8) RetrieveUpdateAPIView
# 提供 get/put  -pk

# 继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin
(9)RetrieveDestroyAPIView
# 提供 get/delete -pk

# 继承自: GenericAPIView、RetrieveModelMixin、DestroyModelMixin

编写五个接口

案例一、单个使用 - all pk 方法:1-5
路由层
from django.urls import path, re_path, include
from app03_views import views

urlpatterns = [

    # GenericAPIView + 九个子类
    # 增、删、改、查
    path('books4/', views.BooksGenericAPIViewMixinView.as_view()),
    re_path(r'^books4/(?P<pk>\d+)/', views.BookGenericAPIViewMixinView.as_view()),]
视图层
from rest_framework.response import Response
from app03_views.ser import BookSerializers
from app03_views import models
from rest_framework.generics import ListAPIView, CreateAPIView
from rest_framework.generics import RetrieveAPIView, UpdateAPIView, DestroyAPIView

# GenericAPIView + 九个视图子类 -单个子类,多继承 - get/put/delete -pk
class BookGenericAPIViewMixinView(RetrieveAPIView, UpdateAPIView, DestroyAPIView):
    queryset = models.Book.objects.all() # 传入queryset对象
    serializer_class = BookSerializers  # 序列化类
    lookup_field = 'pk'  # 查询字段 - 设置单个
    lookup_url_kwarg = None  # 查询字段 - 设置多个


# GenericAPIView + 九个视图子类 - 单个子类,多继承 - get/post -all
class BooksGenericAPIViewMixinView(ListAPIView, CreateAPIView):
    queryset = models.Book.objects.all() # 传入queryset对象
    serializer_class = BookSerializers  # 序列化类
    lookup_field = 'pk'  # 查询字段 - 设置单个
    lookup_url_kwarg = None  # 查询字段 - 设置多个

案例二 、联合使用 - all / pk 方法:6-7
路由层
from django.urls import path, re_path, include
from app03_views import views

urlpatterns = [


    # get/post -all
    path('books5/', views.Books2GenericAPIViewMixinView.as_view()),
    # get/put/delete - pk
    re_path(r'^books5/(?P<pk>\d+)/', views.Book2GenericAPIViewMixinView.as_view()),]
视图层
from rest_framework.response import Response
from app03_views.ser import BookSerializers
from app03_views import models
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
# GenericAPIView + 九个视图子类 - 多个子类,单继承 - get/put/delete -pk
class Book2GenericAPIViewMixinView(RetrieveUpdateDestroyAPIView):
    queryset = models.Book.objects  # 传入queryset对象
    serializer_class = BookSerializers  # 序列化类
    lookup_field = 'pk'  # 查询字段 - 设置单个
    lookup_url_kwarg = None  # 查询字段 - 设置多个


# GenericAPIView + 九个视图子类 -  多个子类,单继承 - get/post -all
class Books2GenericAPIViewMixinView(ListCreateAPIView):
    queryset = models.Book.objects  # 传入queryset对象
    serializer_class = BookSerializers  # 序列化类
    lookup_field = 'pk'  # 查询字段 - 设置单个
    lookup_url_kwarg = None  # 查询字段 - 设置多个
案例三、联合使用 - pk 方法:8-9
路由层
from django.urls import path, re_path, include
from app03_views import views

urlpatterns = [

    # get/delete - pk
    re_path(r'^books6/(?P<pk>\d+)/', views.Book3GenericAPIViewMixinView.as_view()),
    # get/put - pk
    re_path(r'^books7/(?P<pk>\d+)/', views.Books4GenericAPIViewMixinView.as_view()),]
视图层
from rest_framework.response import Response
from app03_views.ser import BookSerializers
from app03_views import models
from rest_framework.generics import RetrieveDestroyAPIView,RetrieveUpdateAPIView
# GenericAPIView + 九个视图子类 - 多个子类,单继承 - get/delete -pk
class Book3GenericAPIViewMixinView(RetrieveDestroyAPIView):
    queryset = models.Book.objects.all() # 传入queryset对象
    serializer_class = BookSerializers  # 序列化类
    lookup_field = 'pk'  # 查询字段 - 设置单个
    lookup_url_kwarg = None  # 查询字段 - 设置多个


# GenericAPIView + 九个视图子类 -  多个子类,单继承 - get/put -pk
class Books4GenericAPIViewMixinView(RetrieveUpdateAPIView):
    queryset = models.Book.objects  # 传入queryset对象
    serializer_class = BookSerializers  # 序列化类
    lookup_field = 'pk'  # 查询字段 - 设置单个
    lookup_url_kwarg = None  # 查询字段 - 设置多个

2.4 视图集基类ViewSet

2.4.1 ViewSetMixin

源码分析
from rest_framework.viewsets import 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
使用
路由层
from django.urls import path, re_path, include
from app03_views import views

urlpatterns = [
    # ViewSetMixin as_view(cls, actions=None, **initkwargs)
    # 可以为不同请求方式指定 执行不同的方法    
    path('books8/', views.BookViewSetMixin.as_view({'get': 'get_all_data'})),]
视图层
from rest_framework.views import APIView
from rest_framework.response import Response
from app03_views.ser import BookSerializers
from app03_views import models
from rest_framework.viewsets import ViewSetMixin
# 重写APIView 的 as_view()方法,需要传入action
# 如 BookViewSetMixin.as_view({'get':'get_all_data'})
class BookViewSetMixin(ViewSetMixin,APIView):  # ViewSetMixin一定要在APIView前面
    def get_all_data(self,request):
        obj = models.Book.objects.all()
        # The serializer field might be named incorrectly
        # and not match any attribute or key on the `QuerySet` instance.
        # 加 many = True 获取多个obj
        ser = BookSerializers(instance= obj,many=True)
        return Response(ser.data)

2.4.2常用视图集父类

(1) ViewSet
继承关系: APIView + ViewSetMixin

作用: 1. 拥有APIView 的基本功能,提供了身份认证、权限校验、流量管理等。

​ 2.继承ViewSetMixin 在调用as_view()时需用字段传值

​ 格式: 请求方式 : 函数内存地址 - 这个地方可以是任意函数了,但是要符合规范

​ 写法:as_view({'get':'list'})

注意

​ 在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。

路由层
# urls.py
from django.urls import path, re_path, include
from app03_views import views

urlpatterns = [
     # ViewSetMixin as_view(cls, actions=None, **initkwargs)
    re_path(r'^books9/', views.BookViewSet.as_view({'post': 'post_data'})),]
视图层
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from app03_views.ser import BookSerializers
from app03_views import models
from rest_framework.viewsets import ViewSetMixin
# 继承了 APIView + ViewSetMixin
class BookViewSet(ViewSet):
    # 自己定义的方法,把这个方法映射给get请求方式,满足get请求的时候,会执行这个
    def post_data(self,request):
        ser = BookSerializers(data=request.data)
        if ser.is_valid():
            ser.save()
        return Response(ser.data)
(2) GenericViewSet
继承关系: GenericAPIViewViewSetMixin

作用:1.拥有了GenericAPIView 的基本功能,序列化简单、可添加 五个扩展类

​ 2..继承ViewSetMixin 在调用as_view()时需用字段传值

​ 格式: 请求方式 : 函数内存地址 - 这个地方可以是任意函数了,但是要符合规范

​ 写法:as_view({'get':'list'})

注意

​ 在GenericViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。

路由层
from django.urls import path, re_path, include
from app03_views import views

urlpatterns = [

    # ViewSetMixin as_view(cls, actions=None, **initkwargs)
    re_path(r'^books10/(?P<pk>\d+)/', views.BookGenericViewSet.as_view({'get':'get','put':'put_update','delete':'del_destroy'})),]

视图层
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from app03_views.ser import BookSerializers
from app03_views import models
# 五个扩展类
from rest_framework.mixins import ListModelMixin, CreateModelMixin
from rest_framework.mixins import RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
# 视图集父类
from rest_framework.viewsets import GenericViewSet

# 继承了 GenericAPIView + ViewSetMixin
class BookGenericViewSet(GenericViewSet, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = models.Book.objects.all()   
    serializer_class = BookSerializers

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

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

    def del_destroy(self, reuest, pk):
        return self.destroy(reuest, pk)

(3) ModelViewSet
继承关系: GenericViewSet

扩展关系:

ListModelMixinRetrieveModelMixinCreateModelMixinUpdateModelMixinDestoryModelMixin

作用:1.拥有了GenericViewSet的基本功能,序列化简单、

​ 2. 在GenericViewSet的基础上,继承了 五个扩展类

​ 3.继承ViewSetMixin 在调用as_view()时需用字段传值

​ 格式: 请求方式 : 函数内存地址 - 这个地方可以是任意函数了,但是要符合规范

​ 写法:as_view({'get':'list'})

注意

​ 在GenericViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。

在这里我要解释一件事,防止自己以后会忘记:为什么ModelViewSet的视图层,我没有重写方法

但是,为什么五种接口都能实现呢,那是因为,当自己本身类找不到的时候,会向里面再找,因为自己本身类,继承了五个扩展类方法,当你看到里面内部源码时候,你会发现,他们本身就是方法,就像你return 去调用这个方法一样,在这里还有补充一句:任何时候都要记住self的查找顺序,对象 类 父类 父类的父类 依次类推,如果是多继承关系,那么可以使用 ' 类.mro() ' 去看,时间长了确实也记不住那个查找顺序了。

路由层
from django.urls import path, re_path
from app03_views import views

urlpatterns = [

    # ModelViewSet - all -  BookModelViewSet
    path('books11/', views.BookModelViewSet.as_view({'get': 'list', 'post': 'create'})),
    # ModelViewSet - pk -BookModelViewSet
    re_path(r'^books11/(?P<pk>\d+)/',
            views.BookModelViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),


]
视图层
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from app03_views.ser import BookSerializers
from app03_views import models
# 视图集父类
from rest_framework.viewsets import ModelViewSet

# 继承了 GenericViewSet + 五个扩展类
# ModelViewSet - pk
class BookModelViewSet(ModelViewSet):
    queryset = models.Book.objects.all()   
    serializer_class = BookSerializers

(4) ReadOnlyModelViewSet
继承关系: GenericViewSet

扩展关系:

ListModelMixinRetrieveModelMixin

作用:1.拥有了GenericViewSet的基本功能,序列化简单、

​ 2. 在GenericViewSet的基础上,继承了 五个扩展类

​ 3.继承ViewSetMixin 在调用as_view()时需用字段传值

​ 格式: 请求方式 : 函数内存地址 - 这个地方可以是任意函数了,但是要符合规范

​ 写法:as_view({'get':'list'})

注意

​ 在GenericViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。

继承自GenericViewSet,同时包括了。

这个同 ModelViewSet(不过多介绍了) ,需要用的时候,使用ModelViewSet就行了

二、视图总结

后面会做一个关于视图类的一个关系图

posted @   派森的猫  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示