Django -- DRF 中的 视图 详解

版权声明:转载请标明出处 https://blog.csdn.net/gymaisyl/article/details/84111063

两个基类的介绍

Ⅰ. 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扩展类。

支持定义的属性

  1. 列表视图与详情视图通用:
  • queryset 列表视图的查询集
  • serializer_class 视图使用的序列化器
  1. 列表视图使用:
  • pagination_class 分页控制类
  • filter_backends 过滤控制后端
  1. 详情页视图使用:
  • 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。 在试图中可以调用该方法获取详情信息的模型类对象。

扫描二维码关注公众号,回复: 4215778 查看本文章

若详情访问的模型类对象不存在,会返回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())

扩展类

Ⅲ . 五个扩展类

  1. ListModelMixin: 快速实现列表视图,返回200状态码。
    该Mixin的list方法会对数据进行过滤和分页。
# 查询所有书籍的信息
class BookInfoAPIView(ListModelMixin, GenericAPIView):
    # 定义视图的查询集
    queryset = BookInfo.objects.all()
    # 指定视图对应的序列化器
    serializer_class = BookInfoModelSerializer

    def get(self, request):
        return self.list(request)
  1. 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())
  1. 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())
  1. 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)
  1. 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装饰器可以接收两个参数:

  1. methods: 该action支持的请求方式,列表传递
  2. 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直接导出的,可以根据图示将视图之间的继承关系梳理清楚。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/gymaisyl/article/details/84111063