Django -- DRF 中的 视图 详解
两个基类的介绍
Ⅰ. APIView
介绍:APIView
是REST framework提供的所有视图的基类,继承自Django的View父类。
APIView与View的不同之处在于:
- 传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
- 视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
- 任何APIException异常都会被捕获到,并且处理成合适的响应信息;
- 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。
案例一:完成所有书籍的展示查询
继承于APIView,代码实现如下:
# views.py 部分代码
from rest_framework.views import APIView
from rest_framework.response import Response
class BookInfoAPIView(APIView):
books = BookInfo.objects.all()
serializer = BookInfoModelSerializer
def get(self, request):
s = self.serializer(self.books, many=True)
return Response(s.data)
# urls.py 中的 url
url(r'books/', views.BookInfoAPIView.as_view())
Ⅱ. **GenericAPIView**
介绍:
继承自APIView,增加了对于列表视图和详情视图可能用到的通用支持方法。通常使用时,可搭配一个或多个Mixin扩展类。
支持定义的属性:
- 列表视图与详情视图通用:
- queryset 列表视图的查询集
- serializer_class 视图使用的序列化器
- 列表视图使用:
- pagination_class 分页控制类
- filter_backends 过滤控制后端
- 详情页视图使用:
-
lookup_field:查询单一数据库对象时使用的条件字段,默认为’pk’
-
lookup_url_kwarg :查询单一数据时URL中的参数关键字名称,默认与look_field相同。
提供的方法:
列表视图与详情视图通用:
- get_queryset : 获取视图对应的查询集,是列表视图和详细视图获取数据的基础;默认返回的是
queryset
的属性,可重写 - get_serializer_class : 获取序列化器类,默认返回的是
serializer_class
,可重写; - get_serializer(self, args, *kwargs) :
获取序列化器对象,这一步相对于APIView来说,就免去了创建序列化对象;
详情视图使用:
get_object(self) : 返回详情视图所需的模型类数据对象,默认使用lookup_field参数来过滤queryset。 在试图中可以调用该方法获取详情信息的模型类对象。
若详情访问的模型类对象不存在,会返回404。
该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。
案例二:需求:查询某个书籍的具体信息
继承GenericAPIView实现的代码:
# views.py 部分代码
class BookInfoAPIView(GenericAPIView):
# 定义视图的查询集
queryset = BookInfo.objects.all()
# 指定视图对应的序列化器
serializer_class = BookInfoModelSerializer
def get(self, request, pk):
# 需求: 查询某个书籍的详细信息
book = self.get_object()
# 获取序列化对象
ser = self.get_serializer(book)
return Response(ser.data)
# urls.py 中的 url
url(r'books/(?P<pk>\d+)/$', views.BookInfoAPIView.as_view())
扩展类
Ⅲ . 五个扩展类
-
ListModelMixin: 快速实现列表视图,返回200状态码。
该Mixin的list方法会对数据进行过滤和分页。
# 查询所有书籍的信息
class BookInfoAPIView(ListModelMixin, GenericAPIView):
# 定义视图的查询集
queryset = BookInfo.objects.all()
# 指定视图对应的序列化器
serializer_class = BookInfoModelSerializer
def get(self, request):
return self.list(request)
-
CreateModelMixin: 快速实现创建资源的视图,成功返回201状态码。
如果序列化器对前端发送的数据验证失败,返回400错误。
# 创建数据
class BookInfoAPIView(CreateModelMixin, GenericAPIView):
# 定义视图的查询集
queryset = BookInfo.objects.all()
# 指定视图对应的序列化器
serializer_class = BookInfoModelSerializer
def post(self, request):
return self.create(request)
# urls.py
url(r'books/', views.BookInfoAPIView.as_view())
-
RetrieveModelMixin: 可以快速实现返回一个存在的数据对象。
如果存在,返回200, 否则返回404。
class BookInfoAPIView(RetrieveModelMixin, GenericAPIView):
# 定义视图的查询集
queryset = BookInfo.objects.all()
# 指定视图对应的序列化器
serializer_class = BookInfoModelSerializer
def get(self, request, pk):
return self.retrieve(request)
# urls.py
url(r'books/(?P<pk>\d+)/$', views.BookInfoAPIView.as_view())
-
UpdateModelMixin: 更新视图扩展类,提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。
同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。
成功返回200,序列化器校验数据失败时,返回400错误。
class BookInfoAPIView(UpdateModelMixin, GenericAPIView):
# 定义视图的查询集
queryset = BookInfo.objects.all()
# 指定视图对应的序列化器
serializer_class = BookInfoModelSerializer
def put(self, request, pk):
book = self.get_object()
return self.update(request, book)
-
DestroyModelMixin: 删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。
成功返回204,不存在返回404。
视图集
Ⅳ . ViewSet 视图集
常用视图集的父类:
1) ViewSet
继承自APIView,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。
在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。
2)GenericViewSet
继承自GenericAPIView,作用也与GenericAPIVIew类似,提供了get_object、get_queryset等方法便于列表视图与详情信息视图的开发。
3)ModelViewSet
继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
4)ReadOnlyModelViewSet
继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin
action属性:
比如:
urlpatterns = [
url(r’^books/ $ ‘, views.BookInfoViewSet.as_view({‘get’: ‘list’})),
url(r’^books/latest/$ ‘, views.BookInfoViewSet.as_view({‘get’: ‘latest’})),
url(r’^books/(?P\d+)/$ ‘, views.BookInfoViewSet.as_view({‘get’: ‘retrieve’})),
url(r’^books/(?P\d+)/read/$’ , views.BookInfoViewSet.as_view({‘put’: ‘read’})),
]
在视图集中,我们可以通过action对象属性来获取当前请求视图集时的action动作是哪个
现在以ModelViewSet 做代码案例演示:
class BookInfoAPIView(ModelViewSet):
# 定义视图的查询集
queryset = BookInfo.objects.all()
# 指定视图对应的序列化器
serializer_class = BookInfoModelSerializer
# url.py中的urlatterns配置
url(r'books/(?P<pk>\d+)/$', views.BookInfoAPIView.as_view({'get': 'retrieve'})),
url(r'books/', views.BookInfoAPIView.as_view({'get': 'list'}))
在继承了ModelViewSet之后,我们只要在路由中配置的时候,说明什么请求对应什么action,就可以很简单的完成视图函数的关于数据库的简单的增删改查。
Ⅴ . 路由router
上面的方式定义路由,相对来说,还是比较繁琐的,我们现在可以使用更简单的。
REST framework提供了两个router:
- SimpleRouter
- DefaultRouter
DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。
使用方法:
(1):创建router对象,并注册视图集
from rest_framework import routers
router = routers.SimpleRouter()
router.register(r'books', BookInfoAPIView, base_name='book')
register(prefix, viewset, base_name)
- prefix 该视图集的路由前缀
- viewset 视图集
- base_name 路由名称的前缀
(2):添加路由数据到urlpatterns中
有下面两种方式都可以
urlpatterns = [
...
]
urlpatterns += router.urls
urlpatterns = [
...
url(r'^', include(router.urls))
]
路由router形成URL的方式:
Ⅵ . 视图集中定义附加action动作
虽然ModelViewSet给我们提供了很简单的定义视图函数的方法,但是,并不能满足咱们的所有需求,所以我们得需要自己定义action动作。
添加自定义动作需要使用rest_framework.decorators.action
装饰器。
以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。
action装饰器可以接收两个参数:
- methods: 该action支持的请求方式,列表传递
- detail: 表示是action中要处理的是否是视图资源的对象(即是否通过url路径获取主键)
detail参数:
- True 表示使用通过URL获取的主键对应的数据对象
- False 表示不使用URL获取主键
class BookInfoAPIView(ModelViewSet):
# 定义视图的查询集
queryset = BookInfo.objects.all()
# 指定视图对应的序列化器
serializer_class = BookInfoModelSerializer
# 自定义action动作
@action(methods=['get'], detail=False)
def latest(self, request):
# 本action是获取最新的书
book = BookInfo.objects.latest('id')
ser = self.get_serializer(book)
return Response(ser.data)
视图关系一览
Ⅶ. 视图函数继承关系
这个是从pycharm直接导出的,可以根据图示将视图之间的继承关系梳理清楚。