Class-based Views
Django‘s class-based views are a welcome departure from the old-style views.
REST框架提供了一个APIView
类,which subclasses Django‘s View
class.
APIView
类与普通View
类有以下不同:
- 传递给the handler methods 的Requests 将是REST框架的
Request
实例,而不是Django的HttpRequest
实例。 - Handler methods 可能返回REST框架的
Response
,而不是Django的HttpResponse
。该视图将管理 content negotiation并根据响应设置正确的渲染器。 - 任何
APIException
异常都将被捕获并被调解为适当的响应。 - 在请求发送到处理程序方法之前,传入请求将被认证,并运行适当的permission and/or throttle checks。
使用APIView
类与常规View
类一样,像往常一样,传入的请求被调度到适当的处理程序方法,例如.get()
或.post()
。另外,可以在控制API策略的各个方面的类上设置许多属性。
例如:
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import authentication, permissions class ListUsers(APIView): """ View to list all users in the system. * Requires token authentication. * Only admin users are able to access this view. """ authentication_classes = (authentication.TokenAuthentication,) permission_classes = (permissions.IsAdminUser,) def get(self, request, format=None): """ Return a list of all users. """ usernames = [user.username for user in User.objects.all()] # 列表解析的方式返回所有用户名 return Response(usernames)
API策略的属性
以下属性控制了API视图的 the pluggable aspects。
.renderer_classes
.parser_classes
.authentication_classes
.throttle_classes
.permission_classes
.content_negotiation_class
API策略的实例化方法
REST框架使用以下方法来实例化各种可插拔API策略。通常不需要覆盖这些方法。
.get_renderers(self)
.get_parsers(self)
.get_authenticators(self)
.get_throttles(self)
.get_permissions(self)
.get_content_negotiator(self)
.get_exception_handler(self)
API策略的实施方法
调度到处理程序方法之前调用以下方法。
.check_permissions(self,request)
.check_throttles(self,request)
.perform_content_negotiation(self,request,force = False)
调度方式
以下方法由视图的.dispatch()
方法直接调用。这些方法执行任何需要在.get()
,.post()
,put()
,patch()
和.delete()
等handler methods调用之前或之后发生的操作。
.initial(self,request,* args,** kwargs)
在调用 the handler method之前执行任何需要发生的操作。此方法用于执行权限和限制,并执行内容协商。
通常您不需要覆盖此方法。
.handle_exception(self,exc)
the handler method 抛出的任何异常都将传递给此方法,该方法返回一个Response
实例,或重新引发异常。
The default implementation 处理任何 rest_framework.exceptions.APIException
的子类,以及Django Http404
和PermissionDenied
异常,并返回适当的错误响应。
如果您需要自定制API返回的错误响应,则应该对此方法进行子类化。
.initialize_request(self,request,* args,** kwargs)
确保传递给handler方法的请求对象是一个 Request
的实例,而不是通常的Django HttpRequest
。
通常您不需要覆盖此方法。
.finalize_response(self,request,response,* args,** kwargs)
确保从 the handler method返回的任何Response
对象被渲染为 the content negotiation所确定的正确内容类型。
通常您不需要覆盖此方法。
Function Based Views
CBV不总是最好的解决方案。
- 尼克·考格兰
REST框架还允许使用常规的FBV。它提供了一组简单的、绑定到FBV的装饰器,以确保它们接收到一个Request
实例(而不是通常的Django HttpRequest
实例),并允许它们返回Response
(而不是Django HttpResponse
),还允许您配置请求的处理方式。
@api_view()
签名: @api_view(http_method_names=[‘GET‘], exclude_from_schema=False)
这个功能的核心是api_view
装饰器,它提供了一系列视图应该响应的HTTP方法。例如,这是如何编写一个非常简单的、只能手动返回一些数据的视图:
from rest_framework.decorators import api_view @api_view() def hello_world(request): return Response({"message": "Hello, world!"})
这个视图将使用在settings中指定的、默认的 renderers, parsers, authentication classes等
默认情况下,只接受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!"})
You can also mark an API view as being omitted from any auto-generated schema, using the exclude_from_schema
argument.:
@api_view([‘GET‘], exclude_from_schema=True) def api_docs(request): ...
API策略装饰器
要覆盖默认设置,REST框架提供了一组其他的可以添加到视图的装饰器。这些装饰器一定要放在的@api_view
装饰器的下面。例如,要使用 throttle 创建一个每天只能由特定用户调用一次的视图,请使用@throttle_classes
装饰器,passing a list of throttle classes:
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(...)
这些装饰器中的每一个都需要一个参数,它必须是列表或元组元素。