Django -- DRF 中的 【视图 】详解

㈠. APIView

介绍:

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

APIView与View的不同之处在于

  • 传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象,REST framework 提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典对象保存到Request对象中;
  • 视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
  • 任何APIException异常都会被捕获到,并且处理成合适的响应信息;
  • 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。

源代码:

# 1.经过Parser解析器的request
 def get_parser_context(self, http_request):
        """
        Returns a dict that is passed through to Parser.parse(),
        as the `parser_context` keyword argument.
        """
        # Note: Additionally `request` and `encoding` will also be added
        #       to the context by the Request object.
        return {
            'view': self,
            'args': getattr(self, 'args', ()),
            'kwargs': getattr(self, 'kwargs', {})
        }
# 2.经过render处理的response
 def get_renderer_context(self):
        """
        Returns a dict that is passed through to Renderer.render(),
        as the `renderer_context` keyword argument.
        """
        # Note: Additionally 'response' will also be added to the context,
        #       by the Response object.
        return {
            'view': self,
            'args': getattr(self, 'args', ()),
            'kwargs': getattr(self, 'kwargs', {}),
            'request': getattr(self, 'request', None)
        }
# 3.经过异常捕获的
    def get_exception_handler_context(self):
        """
        Returns a dict that is passed through to EXCEPTION_HANDLER,
        as the `context` argument.
        """
        return {
            'view': self,
            'args': getattr(self, 'args', ()),
            'kwargs': getattr(self, 'kwargs', {}),
            'request': getattr(self, 'request', None)
        }
# 4.权限认证,身份认证,流量监控
 def permission_denied(self, request, message=None):
        """
        If request is not permitted, determine what kind of exception to raise.
        """
        if request.authenticators and not request.successful_authenticator:
            raise exceptions.NotAuthenticated()
        raise exceptions.PermissionDenied(detail=message)

    def throttled(self, request, wait):
        """
        If request is throttled, determine what kind of exception to raise.
        """
        raise exceptions.Throttled(wait)

    def get_authenticate_header(self, request):
        """
        If a request is unauthenticated, determine the WWW-Authenticate
        header to use for 401 responses, if any.
        """
        authenticators = self.get_authenticators()
        if authenticators:
            return authenticators[0].authenticate_header(request)

案例一:完成所有书籍的展示查询

继承于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 视图使用的序列化器
  2. 列表视图使用:

    • pagination_class 分页控制类
    • filter_backends 过滤控制后端
  3. 详情页视图使用:

    • lookup_field:查询单一数据库对象时使用的条件字段,默认为’pk’
    • lookup_url_kwarg :查询单一数据时URL中的参数关键字名称,默认与look_field相同。

提供的方法:

列表视图与详情视图通用:

  • get_queryset : 获取视图对应的查询集,是列表视图和详细视图获取数据的基础;默认返回的是queryset 的属性,可重写

  • get_serializer_class : 获取序列化器类,默认返回的是serializer_class,可重写;

  • get_serializer(self, args, *kwargs) :
    获取序列化器对象,这一步相对于APIView来说,就免去了创建序列化对象;

  • get_serializer_context(self):
    这个是给序列化器返回的一个context属性,context属性里面有‘request’,‘format’,‘view’值可以在序列化器类中使用。

详情视图使用:

get_object(self) : 返回详情视图所需的模型类数据对象,默认使用lookup_field参数来过滤queryset。 在试图中可以调用该方法获取详情信息的模型类对象。

若详情访问的模型类对象不存在,会返回404。

该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。

源代码:- -太长了,就把有的一些方法直接直接截图
Django -- DRF 中的 【视图 】详解_第1张图片


案例二:需求:查询某个书籍的具体信息

继承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\d+)/$', views.BookInfoAPIView.as_view())

㈢ . 五个扩展类

  1. ListModelMixin: 快速实现列表视图,返回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)
  • 案例说明
# 查询所有书籍的信息
class BookInfoAPIView(ListModelMixin, GenericAPIView):
    # 定义视图的查询集
    queryset = BookInfo.objects.all()
    # 指定视图对应的序列化器
    serializer_class = BookInfoModelSerializer

    def get(self, request):
        return self.list(request)
  1. CreateModelMixin: 快速实现创建资源的视图,成功返回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 {}
  • 案例分析
#  创建数据 
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 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 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\d+)/$', views.BookInfoAPIView.as_view())
  1. 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)
  • 案例
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。
  • 源代码:
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()

你可能感兴趣的:(Django扩展)