概述

APIView是DRF的视图层中最基本的类,它相当于Django中的View类,其他视图类都是通过继承APIView实现的。

GenericAPIView继承于APIView,在其父类的基础上为列表视图和详情视图添加了常用的行为。

Mixins提供了一些基本视图行为的操作方法,如提供的list()方法将返回查询集,等等。因为Python多继承的特性,因此,在定义视图时可以将GenericAPIView和Mixins进行灵活的组合。而DRF中就提供了许多这样的类可以供我们完成所有所需的View。

1.APIView

在DRF中提供了APIView,继承于Django的View,作为最基本的类视图,处理用户的请求并返回响应。和View相比,APIView有如下特点:

1.传递给处理方法的请求是DRF的Request实例,而不是Django的HttpRequest实例;
2.响应并返回的是DRF的Response对象,而不是Django的HttpResponse对象;
3.任何APIException异常都会被捕获并调制到适当的响应中;
4.会对接收的请求进行身份认证和权限的检查。
和使用View类似,使用APIView时,接收的请求会被dispatch到对应的方法中,如get()、post()……此外,还可以设置许多属性来控制API各个方面的策略。

使用APIView时需要导入其所在模块:

from rest_framework.views import APIView

基本的使用APIView方式举例如下:

class SnippetList(APIView):

    # 处理GET请求
def get(self, request, format=None): snippet = Snippet.objects.all()
serializer = SnippetSerializer(snippet, many=True)
return Response(serializer.data) # 处理POST请求
def post(self, request, format=None):
serializer = SnippetSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)

  

1.1.常用属性

.authentication_classes

该属性用于指定当前View endpoint的身份验证类,如:

from rest_framework.authentication import TokenAuthentication

class TestView(APIView):

    authentication_classes = (TokenAuthentication,)
# ......

使用authentication_classes设置的身份验证类将仅仅对该View验证有效,如果需要对整个项目有效,则需要在settings.py配置文件中进行设置:

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
# ......
'rest_framework.authentication.authentication.TokenAuthentication',
)
}

DEFAULT_AUTHENTICATION_CLASSES也是身份验证类列表的默认值。

.permission_classes

该属性用于指定当前View endpoint的权限类列表,如:

from rest_framework import permissions
class SnippetList(APIView):
# ...
permission_classes = (permissions.IsAuthenticatedOrReadOnly,permissions.IsAuthenticated,permissions.IsAdminUser)
# ...

如果不指定该属性,则默认使用settings.DEFAULT_PERMISSION_CLASSES中指定的权限列表。

APIView是DRF中所有View的基类,也是DRF中视图层的基础,但APIView并不是重点,重点是下面的GenericAPIView和Mixins以及两个混合组成的许多类。

2.GenericAPIView

GenericAPIView继承于APIView,为常用的列表视图和详细视图提供了一些操作属性方法。

使用GenericAPIView时需要导入对应模块:

from rest_framework import generics

其基本使用方式如下:

from .serializers import SnippetSerializer
from .models import Snippet
# Create your views here. class Show(generics.GenericAPIView): # 指定序列化类
serializer_class = SnippetSerializer
# 指定QuerySet对象
queryset = Snippet.objects.all() def get(self, request):
return Response("hello world...") def post(self, request):
return Response(request.data)

2.1.常用属性和方法

.queryset

指定要显示的Model对象的QuerySet对象(查询集),用于列表视图中。在GenericAPIView中必须指定该属性或者重写get_queryset()方法。

.serializer_class

指定要显示的Model对象的Serializer对象,在GenericAPIView中必须指定该属性或者重写get_serializer()方法。

.lookup_field

指定用于查找单个Model实例的Model字段,默认为pk.

.lookup_url_kwarg

指定用于Model查找的url关键字参数,如果未设置,则默认使用与lookup_field的值。

.pagination_class

指定列表视图中用于分页的分页类列表,可以对响应列表进行分页。默认使用配置文件中DEFAULT_PAGINATION_CLASS的值。

.filter_backends

指定用于过滤查询集的过滤器后端类列表。 默认使用为DEFAULT_FILTER_BACKENDS设置的值。

.get_queryset(self)

返回用于列表视图的查询集,默认返回queryset属性指定的查询集。

NOTE:
应始终使用此方法而不是直接访问self.queryset,因为self.queryset仅被评估一次,然后将结果进行缓存用于所有后续请求。

.get_object(self)

返回用于详情视图中的Model对象实例,默认使用lookup_field字段过滤QuerySet中的数据。

.get_serializer()

返回用于Model序列化的Serializer类,默认返回serializer_class属性的值,该方法可以用来动态指定一个序列化类。

3.Mixin

通常GenericAPIView不会单独使用,因为它相比APIView,仅仅提供了一些公共的用于列表视图和详情视图的属性和方法,GenericAPIView需要和Mixins组合使用。

Mixin类中提供了许多用于对视图进行操作的方法,这些操作方法无须我们自己实现就可以使用了。比如,ListModelMixin提供了一个list()方法用于将Model的查询集响应给客户端,因此可以用于列表视图的get()中:

class show(generics.GenericAPIView,mixins.ListModelMixin):

    serializer_class = SnippetSerializer
queryset = Snippet.objects.all() def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)

相比使用APIView,简化了非常多的操作。

使用Mixins需要导入其所在模块:

from rest_framework import mixins

下面对常用Mixins类及其功能进行下总结。

3.1.ListModelMixin

该类提供了一个.list(request, *args, **kwargs)方法,用于列出查询集QuerySet。如果queryset被填充,则响应码为200,并将查询集序列化作为响应体响应给客户端。

3.2.CreateModelMixin

该类提供一个.create(request, *args, **kwargs)方法,用于创建并保存一个新的Model实例,因此用在POST请求中,和post()方法组合使用。如果Model实例创建成功,则响应码为201 Created ,并将对象序列化后作为响应体响应给客户端;如果Model实例创建失败,则响应码为401(Bad Request),并将错误信息作为响应体。

3.3.RetrieveModelMixin

该类提供一个retrieve(request, *args, **kwargs)方法,用于检索并返回一个现有的Model实例。如果能够检索到对象,则返回200 OK响应,并将对象序列化后作为响应体输出,否则返回404 Not Found响应。

3.4.UpdateModelMixin

该类提供一个update(request, *args, **kwargs)方法,用于更新并保存现有的Model对象。因此用在PUT请求中,和put()方法组合使用。如果更新成功,则返回200 OK响应,并将对象序列化后作为响应体输出,否则返回400 Bad Request响应。

3.5.DestroyModelMixin

该类提供一个.destroy(request, *args, **kwargs)方法,用于删除一个已存在的Model实例。如果删除成功返回204 No Content响应,否则返回404 Not Found响应。

以上方法无须我们再进行实现,直接使用即可,如以下示例:

class SnippetDetail(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
# get,put,delete方法是GenericAPIView中提供
# retrieve,update,destory方法由Mixin类视图提供
# 二者可以灵活的结合
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs) def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs) def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs) def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)

  

4.常用具体通用视图

在DRF中,除了提供Mixin类之外,还提供了GenericAPIView和Mixins的组合View类,这些类称为具体通用视图。因此我们不需要只需要具体通用视图就可以实现我们所需的功能,如:

from rest_framework import generics

class show(generics.ListCreateAPIView):

    serializer_class = SnippetSerializer
queryset = Snippet.objects.all()

在这个示例中,ListCreateAPIView继承自GenericAPIView, ListModelMixin, CreateModelMixin这三个类,并且内部已经将对应请求方法和操作方法进行了实现,我们只需要指定一些属性即可,无须再写get(),post()请求方法逻辑。

下面是一些常用的具体通用视图。
使用这些类时需要导入所在模块:

from rest_framework import generics

4.1.ListCreateAPIView

父类:GenericAPIView,  mixins.ListModelMixin, mixins.CreateModelMixin
特点:已提供了get()、put()方法处理。

4.2.RetrieveUpdateDestroyAPIView

父类:GenericAPIView,  mixins.RetrieveModelMixin,  mixins.UpdateModelMixin,  mixins.DestroyModelMixin
特点:已提供了get()、put()、patch()、destory()方法处理。

4.3.CreateAPIView

父类:GenericAPIView, mixins.CreateModelMixin

特点:已提供了post()方法处理。

4.4.ListAPIView

父类:GenericAPIView, mixins.ListModelMixin

特点:已提供了get()方法处理。

4.5.RetrieveAPIView

父类:GenericAPIView, mixins.RetrieveModelMixin

特点:已提供了get()方法处理。

4.6.DestroyAPIView

父类:GenericAPIView, mixins.DestroyModelMixin,

特点:已提供了delete()方法处理。

4.7.UpdateAPIView

父类:GenericAPIView, mixins.UpdateModelMixin,

特点:已提供了put(), patch()方法处理。

4.8.RetrieveDestroyAPIView

父类:GenericAPIView, mixins.RetrieveModelMixin,mixins.DestroyModelMixin,

特点:已提供了get(), delete()方法处理。

4.9.RetrieveUpdateDestroyAPIView

父类:GenericAPIView, mixins.RetrieveModelMixin,mixins.DestroyModelMixin,mixins.UpdateModelMixin

特点:已提供了get(), delete(), put(), putch()方法处理。

其他具体通用视图,还请参考官方文档.

5.重构View示例

现在,利用以上View内容以及Django中的函数视图等内容,从函数视图开始,一步步对视图进行重构,看看其简化的过程。

Step1.最初的函数视图

# 列表视图
@api_view(['GET', 'POST'])
def student_list(request): # 处理GET请求
if request.method == 'GET': student = Student.objects.all()
serializers = StudentSerializer(student, many=True)
return Response(serializers.data) # 处理POST请求
if request.method == 'POST':
serializer = StudentSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(status=status.HTTP_400_BAD_REQUEST) # 详情视图
@api_view(['GET', 'POST'])
def student_detail(request, pk):
if request.method == 'GET': student = Student.objects.get(pk=pk)
serializer = StudentSerializer(student)
return Response(serializer.data) if request.method == 'POST': serializer = StudentSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(status=status.HTTP_400_BAD_REQUEST)

  

Step2.将函数视图用APIView替换

现在通过APIView进行重构,可以定义请求对应的get()方法和post()方法,重构后如下所示:

from rest_framework.response import Response
from hello.models import Student
from hello.serializers import StudentSerializer
from rest_framework import status
from rest_framework import views # 列表视图
class StudentList(views.APIView): # GET请求
def get(self,request):
student = Student.objects.all()
serializer = StudentSerializer(student,many=True)
return Response(serializer.data) # POST请求
def post(self, request): serializer = StudentSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST) # 详情视图
class StudentDetail(views.APIView): def get(self, request, pk):
student = Student.objects.get(pk=pk)
serializer = StudentSerializer(student)
return Response(serializer.data) def post(self, request):
serializer = StudentSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)

  

Step3.GenericAPIView+Mixins替换APIView

GenericAPIView相比APIView,提供了部分属性;Mixins提供了许多用于对视图进行操作的方法:

from rest_framework.response import Response
from hello.models import Student
from hello.serializers import StudentSerializer
from rest_framework import status
from rest_framework import generics
from rest_framework import mixins
from django.http import Http404 class StudentList(generics.GenericAPIView, minxins.ListModelMixin, mixins.CreateModelMixin): # 指定序列化类
serializer_class = StudentSerializer
# 执行Model对象查询集
queryset = Student.objects.all()
# 如果不对query_set的值进行修改,没有必要重写该方法
def get_queryset(self):
return Student.objects.all() def get(self, request):
return self.list(request) def post(self, request):
return self.create(request) # 详情视图
class StudentDetail(generics.GenericAPIView,
mixins.RetrieveModelMixin): def get(self, request, *args, **kwargs):
return self.retrieve(self, request, *args, **kwargs)

  

Step4.使用具体通用视图替换GenericAPIView+Mixins

from hello.models import Student
from hello.serializers import StudentSerializer
from rest_framework import generics # 列表视图
class StudentList(generics.ListCreateAPIView): serializer_class = StudentSerializer
queryset = Student.objects.all() # 详情视图
class StudentDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Student.objects.all()
serializer_class = StudentSerializer

  

通过具体通用视图,两行代码就搞定。

总结
DRF中提供了这么多View,但无非就是从views.View这个基类,通过继承、mixin实现而已。因此,在学习这些类时,不必死记硬背,而是通过其继承结构、实现源码,了解明白它的作用和使用方式,以及和mixin的混合使用,这样才可以更好的使用DRF中的各种View。

三,APIView、GenericAPIView、Mixins总结的更多相关文章

  1. django-rest-framework-源码解析003-视图家族和路由(APIView/GenericAPIView/mixins/generics/viewsets)

    视图家族 视图家族在rest_framework源码位置和学习曲线为: rest_framework.views: 基本视图(APIView) rest_framework.generics: 工具视 ...

  2. DRF框架(五)——context传参,二次封装Response类,两个视图基类(APIView/GenericAPIView),视图扩展类(mixins),子类视图(工具视图),视图集(viewsets),工具视图集

    复习 1.整体修改与局部修改 # 序列化get (给前端传递参数) #查询 ser_obj = ModelSerializer(model_obj) #只传递一个参数,默认是instance的参数,查 ...

  3. drf框架 - 视图家族 | GenericAPIView | mixins | generics | viewsets

    视图家族 view:视图 generics:工具视图 mixins:视图工具集 viewsets:视图集 学习曲线: APIView => GenericAPIView => mixins ...

  4. DRF中两大视图基类APIView/GenericAPIView的介绍

    (1)APIView rest_framework.views.APIView APIView是REST framework提供的所有视图的基类,继承自Django的View父类. APIView与V ...

  5. DRF框架之视图类

    前后端分离的项目 >: pip3 install djangorestframework   一.视图类传递参数给序列化类 视图层:views.py 需求: (1)在视图类中实列化对象是,可以设 ...

  6. 二次封装 Reponse,视图家族

    复习 """ 1.整体修改与局部修改 # 序列化 ser_obj = ModelSerializer(model_obj) # 反序列化,save() => cre ...

  7. drf二次封装response-APIViews视图家族-视图工具集-工具视图-路由组件

    视图类传递参数给序列化类 (1).在视图类中实例化 序列化对象时,可以设置context内容. (2).在序列化类中的局部钩子.全局钩子.create.update方法中,都可以用self.conte ...

  8. RESTful-rest_framework视图层-第三篇

    图书管理系统: 实现图书接口的增.删.改.查 方式一:普通的方式 views配置: #Book的增.删.改.查接口 class BookSerializer(serializers.ModelSeri ...

  9. GenericAPIView的使用及和视图扩展类的结合使用

    GenericAPIView的使用 from rest_framework.generics import GenericAPIView GenericAPIView继承 APIView,主要增加了操 ...

随机推荐

  1. tomcat安全加固和规范

    tomcat是一个开源Web服务器,基于Tomcat的Web运行效率高,可以在一般的硬件平台上流畅运行,因此,颇受Web站长的青睐.不过,在默认配置下其存在一定的安全隐患,可被恶意攻击.以下是一些安全 ...

  2. JavaScript基础知识点学习记录

    一.简介: JavaScript是一种基于对象和事件驱动并具有相对安全性的客户端脚本语言,同时也是一种广泛用于客户端Web开发的脚本语言,常用来给HTML网页添加动态功能,比如相应用户的各种操作. J ...

  3. 添加删除mysql用户

    create user 'hive_user'@'%' identified by '密码'; grant all privileges on hive.* to hive_user@'%'; cre ...

  4. 数据库数据以Excel的方式导出

    import java.io.Serializable; import java.util.List; import com.cfets.cwap.s.util.db.TableColumn; /** ...

  5. 踩过的坑:InteliIJ IDEA 打开的项目突然左侧目录结构消失了,如何处理?

    试了很多的办法,删除项目,然后重新从git下载,再导入项目,但是对于暂存未上传到git的文件也会被一并删除,这样就亏大发了 之前一直没有找到解决办法,这里记一下终身有效的办法,并且比较好操作 按下列步 ...

  6. 字符串截取函数slice, substring, substr

    在日常项目需求中,常常会遇到需要截取字符串操作的工作,而ECMAScript为我们提供了原生的截取字符串的函数,而且提供了三个:slice, substring, substr.我们怎么判断在什么时候 ...

  7. I/O多路复用 select poll epoll

    I/O多路复用指:通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. select select最早于1983年出现在4.2BSD中,它通 ...

  8. uva-141-枚举

    旋转过程的下标变化,画个2x2的表格,模拟就可以出来了 #include <string> #include<iostream> #include<map> #in ...

  9. scala快速一览

    println("hello world"); val x = +; println(x); //val 不允许再次赋值 //x = 3; //变量var var xx = x; ...

  10. Python学习笔记_week2_列表、元组、字典、字符串、文件、i编码

    一. 列表.元组 names=["A","B","C","D"] print(names) print(names[0] ...