Django REST framework API:Views

Posted by eckid on December 8, 2016

原文

基于类的视图(Class-based Views)

Django基于类的视图是对原有视图的一种受欢迎的颠覆。

Reinout van Rees

REST framework 提供了 APIView 类,它是 Django 中 View 的子类。

APIViewView 的不同之处在于:

  • 传给 handler 方法的请求需要是一个 REST framework 的 Request 实例,而不是 Django 的 HttpRequest 实例。

  • Handler 方法需要return一个REST framework Response,而不是 Django 的 HttpResponse。视图将会负责内容协商以及处理正确的返回值。

  • 所有 APIException 异常都会被捕捉并交由对应的响应。

  • 请求会首先经历认证和权限的校验,通过后再进入handle方法处理。

APIViewView 的用法很类似,请求将会被交由适当的handler处理,例如 .get().post()。另外,我们需要设置一系列属性来配置API的方方面面。

示例:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions

class ListUsers(APIView):
    """
    该视图用于列出系统中所有用户
    * 需要token 认证
    * 只有admin可以查看该视图
    """
    authentication_classes = (authentication.TokenAuthentication,)
    permission_classes = (permissions.IsAdminUser,)

    def get(self, request, format=None):
        """
        返回用户的列表
        """
        usernames = [user.username for user in User.objects.all()]
        return Response(usernames)

API 策略属性 (policy attributes)

下面的属性与 API 视图的可插拔(pluggable aspects)有关。

.renderer_classes

.parser_classes

.authentication_classes

.throttle_classes

.permission_classes

.content_negotiation_class

API 策略实例化方法 (policy instantiation methods)

下列方法用于实例化上述的 API 可插拔(pluggable)策略。 你不需要重写以下方法。

.get_renderers(self)

.get_parsers(self)

.get_authenticators(self)

.get_throttles(self)

.get_permissions(self)

.get_content_negotiator(self)

API 策略实施方法(policy implementation methods)

下面的方法将会在请求下发给handler 之前调用。

.check_permissions(self, request)

.check_throttles(self, request)

.perform_content_negotiation(self, request, force=False)

Dispatch方法

下列的方法将会被视图的 .dispatch() 方法直接调用,可能需要在 .get(), .post(), put(), patch().delete() 这类handler方法前/后调用。

.initial(self, request, *args, **kwargs)

在 handler 方法调用前执行,用于权限限制或者内容协商。

一般不需要重写该方法。

.handle_exception(self, exc)

此函数接受所有 handler 中发生的异常,返回值是一个 Response 实例或者重新触发该异常。

它能够处理所有 rest_framework.exceptions.APIException 的子类,以及 Django 的 Http404PermissionDenied 异常,并返回对应的异常响应。

当你需要定制异常响应时,你应该创建该方法的子类。

.initialize_request(self, request, *args, **kwargs)

用于确保传给 handler 方法的 request 对象是一个 Request实例,而不是 Django HttpRequest

一般不需要重写该方法。

.finalize_response(self, request, response, *args, **kwargs)

该方法确保 handler 方法返回的 Response 对象根据内容协商被渲染为正确的 content type。

一般不需要重写该方法。

基于方法的视图(Function Based Views)

【基于类的视图总是更好的解决方案】这种说法是错误的。

Nick Coghlan

REST framework 允许你使用常规的基于方法的视图,也提供了一些装饰器来包装这种视图,以保证接受到的是 Request 实例(而非 Django 的 HttpRequest) 并且返回 Response (而非 Django 的 HttpResponse),也允许你去配置请求过程。

@api_view()

Signature: @api_view(http_method_names=['GET'])

整个功能的核心就是 api_view 装饰器, 它接收一系列需要进行响应的 HTTP 方法。举例说明,下面的视图只是简单的返回一些数据:

reverse方法一样要传入request做为关键字参数:

from rest_framework.decorators import api_view

@api_view()
def hello_world(request):
    return Response({"message": "Hello, world!"})

该视图将会使用 settings 指定的默认的 renderers, parsers, authentication 等等。

在默认情况下,可以接受 GET 请求,其余请求将会响应 “405 Method Not Allowed”。

使用下面的做法可以添加其他请求:

@api_view(['GET', 'POST'])
def hello_world(request):
    if request.method == 'POST':
        return Response({"message": "Got some data!", "data": request.data})
    return Response({"message": "Hello, world!"})

API 策略装饰器(policy decorators)

如果要覆盖默认设置,可以用REST framework 提供的一些view装饰器。它们必须在 @api_view 装饰器之后(after/below)调用。举例说明,创建一个视图,用 throttle 来保证该视图每天只能被指定用户调用一次,使用 @throttle_classes 装饰器,传递一个由throttle 类构成的列表:

from rest_framework.decorators import api_view, throttle_classes
from rest_framework.throttling import UserRateThrottle

class OncePerDayUserThrottle(UserRateThrottle):
        rate = '1/day'

@api_view(['GET'])
@throttle_classes([OncePerDayUserThrottle])
def view(request):
    return Response({"message": "Hello for today! See you tomorrow!"})

这些装饰器和 APIView 子类中的属性相对应。

可用的装饰器有:

  • @renderer_classes(...)

  • @parser_classes(...)

  • @authentication_classes(...)

  • @throttle_classes(...)

  • @permission_classes(...)

这些装饰器可以接受一个参数,此参数必须是class构成的元组或列表。