2.DRF 请求&响应&视图类

0. 准备环境

* 1. 新建一个项目

image-20220417000727647

* 2. 修改模板路径拼接问题
 'DIRS': [BASE_DIR, 'templates']
* 3. 写一个测试路由
from django.conf.urls import url
from django.contrib import admin

# 导入视图层
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 测试路由
    url(r'^test/', views.Test.as_view())
]
* 4. app列表中注册    'rest_framework'
INSTALLED_APPS = [
    ...
    'rest_framework'
]
* 5. 视图类
from django.shortcuts import render

# Create your views here.

# 导入 APIView
from rest_framework.views import APIView
# 导入 Response
from rest_framework.response import Response


class Test(APIView):
    def get(self, request):
        return Response({
    
    'msg': 'xx'})
* 6. 定义表模型
from django.db import models


# Create your models here.
# 书籍表
class Book(models.Model):
    # id
    id = models.AutoField(primary_key=True, verbose_name='主键')
    # 书名
    title = models.CharField(max_length=32, verbose_name='书名')
    # 价格
    price = models.DecimalField(max_digits=5, decimal_place=2, verbose_name='价格')
    # 出版社
    publish = models.CharField(max_length=32, verbose_name='出版社')
* 7. 生成表
	 生成表记录: python manage.py makemigrations
	 数据库迁移: python manage.py migrate

1. 请求与响应

1.1 Request

from rest_framework.request import Request 
定义视图类的继承了rest_framework的APIView, 传入的视图对象不在是Django默认的HttpRequest对象, 
而是rest_framework的Request类的对象.
# drf 的Request类
class Request:

    def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
        # 断言 传入的request一定要是Django HttpRequest的request
        assert isinstance(request, HttpRequest), (
            'The `request` argument must be an instance of '
            '`django.http.HttpRequest`, not `{}.{}`.'
            .format(request.__class__.__module__, request.__class__.__name__)
        )
		# 二次封装request, 将原来的request, 作为drrf的request对象的_request属性值.
        self._request = request
        ...
        
        
        # 代理的编程模式, 
        def __getattr__(self, attr):
        """
        If an attribute does not exist on this instance, then we also attempt
        to proxy it to the underlying HttpRequest object.
        """
        try:
            # 执行Request的request方法的时候, 让Django的request执行
            return getattr(self._request, attr)
        
        # 换另一种方式再次获取
        except AttributeError:
            return self.__getattribute__(attr)
rest_framework提供Parser解析器, 在接收到请求后, 会自动根据Conter-Type指明的请求数据类型(JSON, 表单等)
将请求数据进行Parser解析, 解析为类字典QueryDict对象保存到Response对象中.
Request对象的数据是自动根据前端发送的数据格式进行解析的, 无论前端发送那种的格式数据都使用统一方式读取.

1.2 Request方法

.data: 
	返回解析之后的起你去体数据, 类似Django的POST, FIELDS属性.
特性: 
    包含了解析之后的文件和非文件数据.
    包含了POST, PUT, PATCH请求方式解析后的数据.
    利用了rest_framework提供Parse解析器, 不仅支持表单类型数据, 还支持JSON数据.
        	
.query_params: 与Django的GET相同, 只是跟换一个名称.

1.3 Response

from rest_framework.response import Response 
rest_farmework提供一个响应类Response, 该类构造响应对象时, 响应的具体数据内容会被转换(render渲染)
符合前端需要的类型.
class Response(SimpleTemplateResponse):
    """
    An HttpResponse that allows its data to be rendered into
    arbitrary media types.
    """

    def __init__(self, data=None, status=None,
                 template_name=None, headers=None,
                 exception=False, content_type=None):
data:  返回的数据
status: 状态码, 默认是200
template_name: 模板, 使用rest_farmework默认页面需要APP应用列表中注册rest_farmework. 可以自定义模板.
headers: 响应头, 在可以在响应头里面存放数据
exception 异常处理
content_type 响应编码格式 text/html application/json
# 修改视图的返回信息
class Test(APIView):
    def get(self, request):
        return Response({
    
    'msg': 'xx'}, status=201, headers={
    
    'token': 'uuid123456'})

2022-04-17_00183

浏览器发送请求渲染成text/html格式, Postman请求返回application/json格式
这个是通过配置文件实现的.

2022-04-17_00181

1.4 响应状态码

rest_farmework提供一个模块记录所有的响应状态信息, 使用'常量'记录对应状态码.
# 导入响应状态码
from rest_framework import status
# status.py
HTTP_100_CONTINUE = 100
HTTP_101_SWITCHING_PROTOCOLS = 101
...
# 以后在返回状态码的时候不推荐写数字, 使用status的'常量'
return Response({
    
    'msg': 'xx'}, status=status.HTTP_200_OK,)

1.5 Response方法

.data: 传给Response对象的序列化之后的的数据, 未render渲染处理.
.status_code: 状态码数字
.content: 经过render处理过的数据, 该数据最后被包裹到HttpResponse对象中返回.

1.6 响应配置

rest_farmework提供Render渲染器, 根据请求头的Accept(接收数据类型声明)自动转换响应数据到对应的格式,
如果, 没有声明会采用默认的方式处理响应数据
1. 全局配置
rest_framework 配置文件查找顺序:
1. 先从自己的视图类中查找
1. 再从项目的配置文件中找
2. 使用drf的默认配置文件
在Django的配置文件中添加
REST_FRAMEWORK = {
    
    
    'DEFAULT_RENDERER_CLASSES':  # 默认响应渲染类
        ('rest_framework.renderers.JSONRenderer',  # JSON渲染
         # 将浏览渲染禁用, 只有在浏览器访问都返回json格式
         # 'rest_framework.renderers.BrowsableAPIRenderer'  # 浏览器渲染
         )
}

image-20220417161653388

2. 局部配置
在视图类中添加配置信息, 优先级最高.
# 1. 导入JSONRenderer配置
from rest_framework.renderers import JSONRenderer
# 2. 为需要设置的类中添加 render_classes属性
renderer_classes = [JSONRenderer, ]
# 导入json格式渲染配置模块
from rest_framework.renderers import JSONRenderer

class Test(APIView):
# 为需要设置的类中添加 render_classes属性 (将全局配置代码注释)
    renderer_classes = [JSONRenderer, ]

    def get(self, request):
        return Response({
    
    'msg': 'xx'}, status=status.HTTP_200_OK, headers={
    
    'token': 'uuid123456'})

2. 视图

rest_farmework 提供的视图主要作用: 
1. 控制序列化器的执行(校验, 保存, 转换)
2. 控制数据库的查询执行

2.1视图基类

1. APIView视图
APIView是rest_framework提供的所有视图基类, 继承Django的View类, 去除CSRF校验, 添加以下功能:
1. 传入到视图方法的request是rest_framework的, 而不是Django的HttpRequest对象.
2. 视图方法可以放回rest_framework的Response对象, 视图会为响应数据设置(render)符合前端要求的格式.
3. 任何APIException异常都会捕获到, 并处理成合适的效应信息.
4. 在进行dispatch()分发前, 会对请求进行身份认证, 权限检测, 流量控制.
   支持定义的类数据:
   身份认证类: authentication_classes = 列表或元组
   权限检测类: permissoin_classes = 列表或元组
   流量控制类: throttle_classes = 列表或元组
使用APIView, 以常规的方式, 在视图类中定义get, post..等方请求法处理请求
使用APIView定义增删该四个接口
* 1. 路由层
, 查全部使用一个路由
输入主键的使用一个路由
    # APIView 不需要主键
    url(r'^api/books/v1/$', views.BooksAPIView1.as_view()),
    # APIView 需要主键
    url(r'^api/books/v1/(?P<pk>\d+)', views.BooksAPIView2.as_view())
* 2. 模型序列化器
在app01下创建Serialization.py文件
# 导入模型序列化亲
from rest_framework import serializers
# 导入表模型
from app01.models import Book
# 导入异常模块
from rest_framework.exceptions import ValidationError


# 定义序列化器
class BookModelSerializer(serializers.ModelSerializer):
    # 定义Meta类
    class Meta:
        model = Book
        fields = '__all__'

* 3. 定义返回数据格式
在app01下创建response_msg.py文件
class BackMsg():
    def __init__(self, code, msg, data):
        self.code = code
        self.msg = msg
        if data:
            self.data = data

    # 返回字典格式数据
    @property
    def get_data(self):
        return self.__dict__
* 4. 视图层
from django.shortcuts import render

# Create your views here.

# 导入 APIView
from rest_framework.views import APIView
# 导入 Response
from rest_framework.response import Response
# 导入响应状态码
from rest_framework import status

# 导入json格式渲染配置模块
from rest_framework.renderers import JSONRenderer

# 导入 响应字典
from app01.response_msg import BackMsg

# 导入模型层
from app01.models import Book

# 导入序列化器
from app01.Serialization import BookModelSerializer


# Books_APIView  查全部 增
class BooksAPIView1(APIView):
    # 查
    def get(self, request):
        # 查询数据库所有的数据, 
        book_obj = Book.objects.all()
        # 转换数据 queryset --> dict
        book_dic = BookModelSerializer(instance=book_obj, many=True)

        # 返回的数据格式
        back_msg = BackMsg(200, '查询成功', book_dic.data)
        return Response(back_msg.get_data)

    # 增
    def post(self, request):
        # 转换数据 json格式字段装 queryset对象
        book_dic = BookModelSerializer(data=request.data)
        # 数据校验
        if book_dic.is_valid():
            # 保存数据
            book_dic.save()
            back_msg = BackMsg(201, '添加成功', book_dic.data)
            return Response(back_msg.get_data)
        else:
            back_msg = BackMsg(203, '添加失败', book_dic.errors)
            return Response(back_msg.get_data)


# BooksAPIView2
class BooksAPIView2(APIView):
    # 查单条数据
    def get(self, request, pk):
        book_obj = Book.objects.filter(pk=pk).first()
        if book_obj:
            # 模型对象转字典
            book_dic = BookModelSerializer(instance=book_obj)

            back_msg = BackMsg(200, '查询成功', book_dic.data)
            return Response(back_msg.get_data)
        else:
            back_msg = BackMsg(101, '数据不存在!', None)
            return Response(back_msg.get_data)

    # 改
    def put(self, request, pk):
        # 获取数据
        book_obj = Book.objects.filter(pk=pk).first()
        # 使用序列化器校验数据
        book_dic = BookModelSerializer(instance=book_obj, data=request.data)
        if book_dic.is_valid():
            # 保存数据
            book_dic.save()
            back_msg = BackMsg(200, '修改成功', book_dic.data)
            return Response(back_msg.get_data,)
        else:
            back_msg = BackMsg(101, '数据校验不成功!', book_dic.errors)
            return Response(back_msg.get_data)

    # 删
    def delete(self, request, pk):
        book_obj = Book.objects.filter(pk=pk).delete()

        if book_obj[0]:
            back_msg = BackMsg(200, '删除成功', None)
            return Response(back_msg.get_data)
        back_msg = BackMsg(101, '删除的数据不存在', None)
        return Response(back_msg.get_data)

2. GenericAPIView
GenericAPIView继承APIView, 只要添加了操作类新华区和数据的查询方法, 作用是为下面Mixin拓展类的执行提供
方法支持. 通常在使用时, 可搭配一个或多个Mixin拓展类.
属性:
	serializer_class: 属性指名使用的序列化器.
方法:
	get_serializer_class(self): 当出现一个视图类中调用多个序列化器, 通过条件判断判断, 
	返回不同的序列化器类名就可以让视图方法执行不同的序列化器对象.
	
	get_serializer(self, args, **kwargs):
	返回序列化亲对象, 只要用来提供Mixin拓展类使用, 如果在数图中想要回去序列化器对象, 也可以调用此方法.
	需要向序列化器对象的context属性补充三个数据, request, format, view, 在定义序列化器时使用.
	request 当前视图的请求对象
	format 当前请求期望返回的数据格式
	view 当前请求的类视图对象
 GenericAPIView定义接口
* 1. 路由
    # GenericAPIView 不需要主键
    url(r'^api/books/v2/$', views.BooksGenericAPIView.as_view()),
    # GenericAPIView 要主键
    url(r'^api/books/v2/(?P<pk>\d+)/', views.BooksGenericAPIView2.as_view()),
* 2.视图类
# 获取所有的模型对象, .all() 如果自己没有写, 会报错!
queryset = Book.objects.all()
get_queryset   获取全部的数据
get_object     获取单条的数据
# 使用的序列化器
serializer_class = BookModelSerializer
self.get_serializer 获取序列化器

GenericAPIView的lookup_field定义了获取单条数据时以pk为查询依据, 
lookup_field = 'pk, 那么有名分组的名字就是pk
可以在自定义类中定义该属性
lookup_field = 'id', 那么有名分组的名字就是id
# 导入GenericAPIView 视图
from rest_framework.generics import GenericAPIView


class BooksGenericAPIView(GenericAPIView):
    # 获取所有的模型对象
    queryset = Book.objects.all()
    # 使用的序列化器
    serializer_class = BookModelSerializer

    # 查
    def get(self, request):
        # 查询数据库所有的数据, 当前对象执行父类的方法
        book_obj = self.get_queryset()
        # 转换数据 queryset --> dict
        book_dic = self.get_serializer(instance=book_obj, many=True)

        # 返回的数据格式
        back_msg = BackMsg(200, '查询成功', book_dic.data)
        return Response(back_msg.get_data)

    # 增
    def post(self, request):
        # 转换数据 json格式字段装 queryset对象
        book_dic = self.get_serializer(data=request.data)
        # 数据校验
        if book_dic.is_valid():
            # 保存数据
            book_dic.save()
            back_msg = BackMsg(201, '添加成功', book_dic.data)
            return Response(back_msg.get_data)
        else:
            back_msg = BackMsg(203, '添加失败', book_dic.errors)
            return Response(back_msg.get_data)


class BooksGenericAPIView2(GenericAPIView):
    # 获取所有的模型对象
    queryset = Book.objects.all()
    # 使用的序列化器
    serializer_class = BookModelSerializer

    # 查单条数据
    def get(self, request, pk):
        book_obj = self.get_object()
        if book_obj:
            # 模型对象转字典
            book_dic = self.get_serializer(instance=book_obj)

            back_msg = BackMsg(200, '查询成功', book_dic.data)
            return Response(back_msg.get_data)
        else:
            back_msg = BackMsg(101, '数据不存在!', None)
            return Response(back_msg.get_data)

    # 改
    def put(self, request, pk):
        # 获取数据
        book_obj = self.get_object()
        # 使用序列化器校验数据
        book_dic = self.get_serializer(instance=book_obj, data=request.data)
        if book_dic.is_valid():
            # 保存数据
            book_dic.save()
            back_msg = BackMsg(200, '修改成功', book_dic.data)
            return Response(back_msg.get_data, )
        else:
            back_msg = BackMsg(101, '数据校验不成功!', book_dic.errors)
            return Response(back_msg.get_data)


    # 删
    def delete(self, request, pk):
        book_obj = self.get_object().delete()

        if book_obj[0]:
            back_msg = BackMsg(200, '删除成功', None)
            return Response(back_msg.get_data)
        back_msg = BackMsg(101, '删除的数据不存在', None)
        return Response(back_msg.get_data)

使用GenericAPIView定义接口, 只要定义好模型对象与序列化记录, 
之后代码更新, 其他的位置都不需要更改, 只需要需要将修改路由,视图类名 queryset serializer_class 修改即可
快速编写接口
* 1. 准备一张publish表
# 出版社表
class Publish(models.Model):
    # id
    id = models.AutoField(primary_key=True, verbose_name='主键')
    # 出版社名字
    name = models.CharField(max_length=32, verbose_name='出版社名字')
    # 邮箱
    email = models.EmailField(verbose_name='邮箱')
    # 地址
    addr = models.CharField(max_length=32, verbose_name='地址')
生成表...
python manage.py makemigrations
python manage.py migrate
* 2. 编写对应的序列化器
# 导入出版社表
from app01.models import Publish


# 定义出版社序列化器
class PublishSerializer(serializers.ModelSerializer):
    # 定义Meta类
    class Meta:
        model = Publish
        fields = '__all__'
* 3. 路由
    # ################################ 出版社 #########################
    # GenericAPIView 不需要主键
    url(r'^api/publishs/v2/$', views.PublishGenericAPIView.as_view()),
    # GenericAPIView 要主键
    url(r'^api/publishs/v2/(?P<pk>\d+)/', views.PublishGenericAPIView2.as_view()),
* 4. 视图, 复制之前的代码, 修改视图类的名称 类的queryset属性, serializer_class方法即可
     接口的定义不需要修改.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0HLu2ESI-1650293308418)(D:/%E6%88%AA%E5%9B%BE/2022-04-18_00188.png)]

lookup_field = 'pk'
lookup_url_kwarg = None
def get_object(self):

    # self.get_queryset()获取数据 放进get_queryset()中过滤
    queryset = self.self.get_queryset()(self.get_queryset())

    # 短路操作 lookup_url_kwarg=None, 那么lookup_url_kwarg = lookup_field = 'pk' 
    lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
	# 断言不看
    assert lookup_url_kwarg in self.kwargs,... 不管

	# filter_kwargs =   {self.pk : self.kwargs['pk']    kwargs是字典{'pk': 1}, 是用名分组传递的值
    filter_kwargs = {
    
    self.lookup_field: self.kwargs[lookup_url_kwarg]}
    # 通过ok主键获取数据, 获取不到就404
    obj = get_object_or_404(queryset, **filter_kwargs)

    # self.request是在APIView的dispatch方法中定义
    self.check_object_permissions(self.request, obj)

    return obj
APIView的dispatch方法为对象定义三个属性, 那么在get_object中才能才能使用self.kwargs, self.queryset
self.args = args 
self.kwargs = kwargs 路由中放的值
self.request = request
在请求函数中, 目前args  kwargs都没有值
print(self.args) ()
print(self.kwargs) {
    
    }
print(self.request) <rest_framework.request.Request object at 0x000001BBC59DFAC8>

2.2 五个数图拓展类

使用了GenericApiView之后, 接口部门代码, 是完全一模一样了, 将重复的代码提取并封装成类.
GenericApiView封装了5个请求的类.
# 导入模块
from rest_framework.mixins import CreateModelMixin,
ListModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
CreateModelMixin: 创建数据模块
ListModelMixin: 查询所有数据
RetrieveModelMixin: 查询单个数据
UpdateModelMixin:跟新数据
DestroyModelMixin: 删除数据

2022-04-18_00190

内部源码, 以自己之前写的逻辑大差不差, 人家写的更加好!
基于GenericApiView使用rest_framework定义的方法快速定义四个接口.
* 1. 路由
    # ############################ 内置方法定义接口 #####################
    url(r'^api/book/v3/$', views.BooksGenericAPIViewMixmin.as_view()),
    url(r'^api/book/v3/(?P<pk>\d+)/', views.BooksGenericAPIViewMixmin2.as_view()),
* 2.视图
# 导入内置创建接口的模块
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin


# 查全部 增
class BooksGenericAPIViewMixmin(GenericAPIView, ListModelMixin, CreateModelMixin):
    # 获取所有的模型对象
    queryset = Book.objects
    # 序列化器
    serializer_class = BookModelSerializer

    # 查全部
    def get(self, request):
        # 将数据放回, 将request对象传递即可
        return self.list(request)

    # 增
    def put(self, request):
        # 将数据返回, 将request对象传递即可
        return self.create(request)


# 查单个, 该, 删
class BooksGenericAPIViewMixmin2(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    # 获取所有的模型对象
    queryset = Book.objects
    # 序列化器
    serializer_class = BookModelSerializer

    # 查单个
    def get(self, request, pk):
        # 将数据返回, 将request对象, 与主键传递
        return self.retrieve(request, pk)

    # 改
    def put(self, request, pk):
        # 将数据返回, 将request对象, 与主键传递
        return self.update(request, pk)
    
    # 删
    def delete(self, request, pk):
        # 将数据返回, 将request对象, 与主键传递
        return self.delete(request, pk)
测试 : 127.0.0.1:8000/api/book/v3/
...

2.3 九个视图子类

1. ListAPIView 提供get方法, 继承GenericAPIView, ListModelMixin
2. CreateAPIView 提供post方法, 继承GenericAPIView, CreateModelMixin
3. RetrieveAPIView 提供get的方法, 继承GenericAPIView RetrieveModelMixin
4. UpdateAPIView 提供put方法和patch方法, 继承GenericAPIView, UpdateModelMixin
5. DestroyAPIView  提供delete方法 继承GenericAPIView, DestoryModelMixin

6. ListCreateAPIView 提供post, get方法方法, 继承GenericAPIView, CreateModelMixin, ListModelMixin
7. RetrieveUpdateDestroyAPIView 提供 get, put, patch, delete方法方法, 继承GenericAPIView
   RetrieveModelMixin, UpdateModelMixin, DestoryModelMixin
   
8. RetrieveUpdateAPIView  提供 get, put, patch方法方法, 继承GenericAPIView
   RetrieveModelMixin, UpdateModelMixin
9. RetrieveDestroyAPIView 提供get, delete方法,  
   继承GenericAPIView, RetrieveModelMixin DestoryModelMixin
# 导入模块
from rest_framework.generics import CreateAPIView, ListAPIView, RetrieveAPIView, DestroyAPIView, UpdateAPIView

2022-04-18_00192

写多个API接口的话定义方法放回数据又重复了, 将重复的代码提取到类中. 该又继承了自定义类需要继承的类.
之后再使用只需要继承子类即可, 在类中定义request属性,  serializer_classd方法即可.
使用数图子类定义接口
* 1. 路由
    # ############################ 内置子类 #####################
    url(r'^api/book/v4/$', views.BooksMixmin.as_view()),
    url(r'^api/book/v4/(?P<pk>\d+)/', views.BooksMixmin2.as_view()),
* 2. 视图
# 查全部 增
class BooksMixmin(CreateAPIView, ListAPIView):
    # 获取所有的模型对象
    queryset = Book.objects
    # 序列化器
    serializer_class = BookModelSerializer


# 查单个, 该, 删
class BooksMixmin2(RetrieveAPIView, UpdateAPIView, DestroyAPIView):
    # 获取所有的模型对象
    queryset = Book.objects
    # 序列化器
    serializer_class = BookModelSerializer
测试 : 127.0.0.1:8000/api/book/v4/
...
(CreateAPIView, ListAPIView) ==> (ListCreateAPIView)
(RetrieveAPIView, UpdateAPIView, DestroyAPIView) ==> (RetrieveUpdateDestroyAPIView)
# 查全部 增
class BooksMixmin(ListCreateAPIView):
    # 获取所有的模型对象
    queryset = Book.objects
    # 序列化器
    serializer_class = BookModelSerializer


# 查单个, 该, 删
class BooksMixmin2(RetrieveUpdateDestroyAPIView):
    # 获取所有的模型对象
    queryset = Book.objects
    # 序列化器
    serializer_class = BookModelSerializer

image-20220418160144810

image-20220418155722965

2.4 视图集

ModelViewSet
ViewSetMixin
ViewSet 
GenericViewSet
ReadOnlyModelViewSet
1. ModelViewSet
将两个视图类合并成一个, 最大的问题就是路由中带主键和不带主键.
rest_framework提供了一个ModelViewSet, 解决上述问题.
ModelViewSet 继承了GenericAPIView,
CreateModelMixin, DestryModelMixin,UpdateModeMixin, RetrieveModelMixin, LinstModelMixin,
GenericAPIView 继承了GenericsAPIView,  ViewSetMixin
# 导入ModelViewSet模块
from rest_framework.viewsets import ModelViewSet


# 定义视图类
class BookModelViewSet(ModelViewSet):
    # 获取所有的模型对象
    queryset = Book.objects
    # 序列化器
    serializer_class = BookModelSerializer

image-20220418161349797

2. ViewSetMixin
在ViewSetMixin定义as_view方法, 解决了路由带主键值与不带主键值的问题.
    # ########################## ModelViewSet  #################################
    url(r'^api/book/v5/$', views.BookModelViewSet.as_view(actions={
    
    'get': 'list', 'post': 'create'})),
    url(r'^api/book/v5/(?P<pk>\d+)/',
        views.BookModelViewSet.as_view(actions={
    
    'get': 'retrieve', 'put': 'update', "delete": "destroy"})),
ViewSetMixin重新了as_view方法, 核心在与view函数.
当路由匹配成功之后, 执行as_view方法, 最后返回view函数地址, 在加括号执行.
view中遍历actions的字典, 为对象添加对应的请求方法, 
最后在dispatch获取当前的请求方式, 通过反射执行 对象.请求名方法.

2022-04-18_00196

在actions的字典中, 为每个请求配置好对应的方法, 方法可以是在视图类中自己写的.
需要注意的点: 继承的顺序不能乱, 想要使用ViewSetMixin的as_view方法, 为对象添加对应的请求方法, 
ViewSetMixin的类或继承了ViewSetMixin类写在第一位.
    # ######################## ModelViewSet 2 ##############################
    url(r'^api/book/v6/$', views.BookModelViewSet.as_view(actions={
    
    'get': 'my_list'})),
class BookModelViewSet2(ModelViewSet):
    # 获取所有的模型对象
    queryset = Book.objects
    # 序列化器
    serializer_class = BookModelSerializer

    # 自定义my_list方法
    def my_list(self, request):
        return self.list(request)
GET 127.0.0.1:8000/api/book/v6/
3. ViewSet
ViewSet 继承了ViewSetMixin 和APIView, 可以自己定义请求执行的方法.
    # ######################## BookViewSet ##############################
    url(r'^api/book/v7/$', views.BookViewSet.as_view(actions={
    
    'get': 'all_obj'})),
# 导入ViewSet模块
from rest_framework.viewsets import ViewSet


class BookViewSet(ViewSet):
    def all_obj(self, request):
        # 获取所有数据
        book_obj = Book.objects.all()
        # 使用序列化器
        book_dic = BookModelSerializer(instance=book_obj, many=True)
        print(book_dic)
        # 组织数据的返回格式
        back_msg = BackMsg(200, '查询成功!', book_dic.data)
        # 返回数据

        return Response(back_msg.get_data)
4. GenericViewSet
GenericViewSet 继承ViewSetMixin和GenericAPIView
    # ############################## GenericViewSet ###########################
    url(r'^api/book/v8/$', views.BookGenericViewSet.as_view(actions={
    
    'get': 'all_obj'}))
# 导入GenericViewSet模块
from rest_framework.viewsets import GenericViewSet


class BookGenericViewSet(GenericViewSet):
    # 获取所有的模型对象
    queryset = Book.objects
    # 序列化器
    serializer_class = BookModelSerializer

    def all_obj(self, request):
        # 查询数据库所有的数据, 当前对象执行父类的方法
        book_obj = self.get_queryset()
        # 转换数据 queryset --> dict
        book_dic = self.get_serializer(instance=book_obj, many=True)
        # 返回的数据格式
        back_msg = BackMsg(200, '查询成功', book_dic.data)
        return Response(back_msg.get_data)
5. ReadOnlyModelViewSet
ReadOnlyModelViewSet 继承了 ListModelMixin  RetrieveModelMixin GenericViewSet
    # ########################### BookReadOnlyModelViewSet ########################
    url(r'^api/book/v9/$', views.BookReadOnlyModelViewSet.as_view(actions={
    
    'get': 'list'})),
    url(r'^api/book/v9/(?P<pk>\d+)/', views.BookReadOnlyModelViewSet.as_view(actions={
    
    'get': 'retrieve'}))
# 导入ReadOnlyModelViewSet模块
from rest_framework.viewsets import ReadOnlyModelViewSet


class BookReadOnlyModelViewSet(ReadOnlyModelViewSet):
    # 获取所有的模型对象
    queryset = Book.objects
    # 序列化器
    serializer_class = BookModelSerializer

3. 视图总结

image-20220418185132801

查看继承关系

3.1 视图基类

1. APIView

image-20220418172136931

2. GenericAPIView

image-20220418172219767

3.2 五个视图拓展类

CreateModelMixin: 创建数据模块
ListModelMixin: 查询所有数据
RetrieveModelMixin: 查询单个数据
UpdateModelMixin:跟新数据
DestroyModelMixin: 删除数据
, 查全部

image-20220418172711633

查单个, , 

image-20220418172740431

3.3 九个子类视图

1. ListAPIView 提供get方法, 继承GenericAPIView, ListModelMixin
2. CreateAPIView 提供post方法, 继承GenericAPIView, CreateModelMixin
3. RetrieveAPIView 提供get的方法, 继承GenericAPIView RetrieveModelMixin
4. UpdateAPIView 提供put方法和patch方法, 继承GenericAPIView, UpdateModelMixin
5. DestroyAPIView  提供delete方法 继承GenericAPIView, DestoryModelMixin

6. ListCreateAPIView 提供post, get方法方法, 继承GenericAPIView, CreateModelMixin, ListModelMixin
7. RetrieveUpdateDestroyAPIView 提供 get, put, patch, delete方法方法, 继承GenericAPIView
   RetrieveModelMixin, UpdateModelMixin, DestoryModelMixin
   
8. RetrieveUpdateAPIView  提供 get, put, patch方法方法, 继承GenericAPIView
   RetrieveModelMixin, UpdateModelMixin
9. RetrieveDestroyAPIView 提供get, delete方法,  
   继承GenericAPIView, RetrieveModelMixin DestoryModelMixin
ListCreateAPIView 提供post, get方法方法

image-20220418173130036

RetrieveUpdateDestroyAPIView 提供 get, put, patch, delete方法方法

image-20220418173333484

3.4 视图集

ModelViewSet 继承了GenericAPIView,
CreateModelMixin, DestryModelMixin,UpdateModeMixin, RetrieveModelMixin, LinstModelMixin,
GenericAPIView 继承了GenericsAPIView,  ViewSetMixin

image-20220418181903012

ViewSet 继承了ViewSetMixin 和APIView

image-20220418181959395

GenericViewSet 继承ViewSetMixin和GenericAPIView

image-20220418182150999

ReadOnlyModelViewSet 继承了 ListModelMixin  RetrieveModelMixin GenericViewSet

image-20220418182256798

猜你喜欢

转载自blog.csdn.net/qq_46137324/article/details/124256839