Django的通用视图…是作为通用用法模式的快捷方式而开发的…它们采用视图开发中发现的某些通用习语和模式并将其抽象化,以便您可以快速编写通用数据视图而不必重复自己。 — Django文档

基于类的视图的主要优点之一是它们允许您组成一些可重用行为的方式。REST框架通过提供许多提供常用模式的预构建视图来利用此优势。

REST框架提供的通用视图使您可以快速构建与数据库模型紧密映射的API视图。

如果通用视图不符合您的API的需求,则可APIView以下拉到使用常规类,或者重用通用视图使用的mixins和基类来组成自己的可重用通用视图集。

例子

通常,在使用通用视图时,您将覆盖视图并设置几个类属性。

  1. from django.contrib.auth.models import User
  2. from myapp.serializers import UserSerializer
  3. from rest_framework import generics
  4. from rest_framework.permissions import IsAdminUser
  5. class UserList(generics.ListCreateAPIView):
  6. queryset = User.objects.all()
  7. serializer_class = UserSerializer
  8. permission_classes = [IsAdminUser]

对于更复杂的情况,您可能还想覆盖视图类上的各种方法。例如。

  1. class UserList(generics.ListCreateAPIView):
  2. queryset = User.objects.all()
  3. serializer_class = UserSerializer
  4. permission_classes = [IsAdminUser]
  5. def list(self, request):
  6. # Note the use of `get_queryset()` instead of `self.queryset`
  7. queryset = self.get_queryset()
  8. serializer = UserSerializer(queryset, many=True)
  9. return Response(serializer.data)

对于非常简单的情况,您可能希望使用.as_view()方法传递任何类属性。例如,您的URLconf可能包含类似以下条目的内容:

  1. path('users/', ListCreateAPIView.as_view(queryset=User.objects.all(), serializer_class=UserSerializer), name='user-list')

API参考

通用API检视

该类扩展了REST框架的APIView类,为标准列表和详细信息视图添加了通常需要的行为。

提供的每个具体的通用视图都是通过将GenericAPIView,和一个或多个mixin类组合而构建的。

属性

基本设定

以下属性控制基本视图行为。

  • queryset-应该用于从该视图返回对象的查询集。通常,您必须设置此属性或重写get_queryset()方法。如果要覆盖视图方法,则必须进行调用get_queryset()而不是直接访问此属性,这queryset将被评估一次,并且这些结果将为所有后续请求缓存,这很重要。
  • serializer_class-应该用于验证和反序列化输入以及序列化输出的序列化器类。通常,您必须设置此属性或重写get_serializer_class()方法。
  • lookup_field-应该用于执行单个模型实例的对象查找的模型字段。默认为'pk'。需要注意的是使用超链接的API时,您需要确保双方的API意见串行类设置查找字段,如果你需要使用一个自定义值。
  • lookup_url_kwarg-用于对象查找的URL关键字参数。URL conf应包含与此值相对应的关键字参数。如果未设置,则默认使用与相同的值lookup_field

分页

与列表视图一起使用时,以下属性用于控制分页。

  • pagination_class-对列表分页时应使用的分页类。缺省值为与DEFAULT_PAGINATION_CLASS设置相同的值'rest_framework.pagination.PageNumberPagination'。设置pagination_class=None将禁用此视图上的分页。

筛选

  • filter_backends-用于过滤查询集的过滤器后端类的列表。默认值为与DEFAULT_FILTER_BACKENDS设置相同的值。

方法

基本方法

get_queryset(self)

返回应用于列表视图的查询集,该查询集应用作详细视图中查找的基础。默认为返回该queryset属性指定的查询集。

应始终使用此方法,而不是self.queryset直接访问该方法,因为它self.queryset只会被评估一次,并且那些结果将为所有后续请求缓存。

可以重写以提供动态行为,例如返回特定于发出请求的用户的查询集。

例如:

  1. def get_queryset(self):
  2. user = self.request.user
  3. return user.accounts.all()

get_object(self)

返回应用于详细信息视图的对象实例。默认为使用lookup_field参数过滤基本查询集。

可以重写以提供更复杂的行为,例如基于多个URL kwarg的对象查找。

例如:

  1. def get_object(self):
  2. queryset = self.get_queryset()
  3. filter = {}
  4. for field in self.multiple_lookup_fields:
  5. filter[field] = self.kwargs[field]
  6. obj = get_object_or_404(queryset, **filter)
  7. self.check_object_permissions(self.request, obj)
  8. return obj

请注意,如果您的API不包含任何对象级权限,则可以选择排除self.check_object_permissions,而只需从get_object_or_404查找中返回对象即可。

filter_queryset(self, queryset)

给定一个查询集,请使用正在使用的任何过滤器后端对其进行过滤,并返回一个新的查询集。

例如:

  1. def filter_queryset(self, queryset):
  2. filter_backends = [CategoryFilter]
  3. if 'geo_route' in self.request.query_params:
  4. filter_backends = [GeoRouteFilter, CategoryFilter]
  5. elif 'geo_point' in self.request.query_params:
  6. filter_backends = [GeoPointFilter, CategoryFilter]
  7. for backend in list(filter_backends):
  8. queryset = backend().filter_queryset(self.request, queryset, view=self)
  9. return queryset

get_serializer_class(self)

返回应该用于序列化程序的类。默认为返回serializer_class属性。

可以重写以提供动态行为,例如使用不同的序列化程序进行读写操作,或为不同类型的用户提供不同的序列化程序。

例如:

  1. def get_serializer_class(self):
  2. if self.request.user.is_staff:
  3. return FullAccountSerializer
  4. return BasicAccountSerializer

保存和删除挂钩

mixin类提供了以下方法,这些方法可以轻松覆盖对象的保存或删除行为。

  • perform_create(self, serializer)-CreateModelMixin保存新对象实例时调用。
  • perform_update(self, serializer)-UpdateModelMixin保存现有对象实例时调用。
  • perform_destroy(self, instance)-DestroyModelMixin删除对象实例时调用。

这些挂钩对于设置隐式存在于请求中但不属于请求数据的属性特别有用。例如,您可以基于请求用户或基于URL关键字参数在对象上设置属性。

  1. def perform_create(self, serializer):
  2. serializer.save(user=self.request.user)

这些覆盖点对于添加在保存对象之前或之后发生的行为(例如通过电子邮件发送确认或记录更新)也特别有用。

  1. def perform_update(self, serializer):
  2. instance = serializer.save()
  3. send_email_confirmation(user=self.request.user, modified=instance)

您还可以通过引发来使用这些挂钩提供其他验证ValidationError()。如果您需要一些验证逻辑以在数据库保存时应用,这将很有用。例如:

  1. def perform_create(self, serializer):
  2. queryset = SignupRequest.objects.filter(user=self.request.user)
  3. if queryset.exists():
  4. raise ValidationError('You have already signed up')
  5. serializer.save(user=self.request.user)

其他方法

尽管使用编写自定义视图时可能需要调用以下方法,但通常不需要重写以下方法GenericAPIView

  • get_serializer_context(self)-返回包含应提供给序列化程序的任何其他上下文的字典。默认为包括'request''view''format'钥匙。
  • get_serializer(self, instance=None, data=None, many=False, partial=False) -返回序列化器实例。
  • get_paginated_response(self, data)-返回分页样式Response对象。
  • paginate_queryset(self, queryset)-如果需要,对查询集进行分页,或者返回页面对象,或者None未为此视图配置分页。
  • filter_queryset(self, queryset) -给定查询集,请使用正在使用的任何过滤器后端对其进行过滤,并返回新的查询集。

混合蛋白

mixin类提供用于提供基本视图行为的操作。请注意,mixin类提供了操作方法,而不是直接定义处理程序方法(例如.get().post())。这样可以更灵活地构成行为。

mixin类可以从导入rest_framework.mixins

ListModelMixin

提供一种.list(request, *args, **kwargs)方法,该方法实现列出查询集。

如果填充了查询集,则返回一个200 OK响应,并以查询集的序列化表示形式作为响应的主体。可以可选地对响应数据进行分页。

CreateModelMixin

提供一种.create(request, *args, **kwargs)方法,该方法实现创建和保存新模型实例。

如果创建了一个对象,它将返回一个201 Created响应,并以对象的序列化表示形式作为响应的主体。如果表示形式包含名为的键url,则将Location使用该值填充响应的标头。

如果提供的用于创建对象的请求数据无效,400 Bad Request则将返回响应,并将错误详细信息作为响应的主体。

检索模型

提供一种.retrieve(request, *args, **kwargs)方法,该方法实现在响应中返回现有模型实例。

如果可以检索到对象,则返回一个200 OK响应,该对象的序列化表示作为响应的主体。否则将返回404 Not Found

UpdateModelMixin

提供一种.update(request, *args, **kwargs)方法,该方法实现更新和保存现有模型实例。

还提供了一种.partial_update(request, *args, **kwargs)方法,该方法与该update方法类似,但是用于更新的所有字段都是可选的。这样可以支持HTTPPATCH请求。

如果对象被更新,则返回一个200 OK响应,该对象的序列化表示作为响应的主体。

如果提供的用于更新对象的请求数据无效,400 Bad Request则将返回响应,并将错误详细信息作为响应的正文。

销毁模型

提供一种.destroy(request, *args, **kwargs)方法,该方法实现删除现有模型实例。

如果删除对象,则返回204 No Content响应,否则将返回404 Not Found


具体的视图类

以下类是具体的通用视图。如果您使用的是通用视图,那么通常这就是您要使用的级别,除非需要大量的自定义行为。

可以从中导入视图类rest_framework.generics

CreateAPIView

用于仅创建端点。

提供post方法处理程序。

扩展:GenericAPIViewCreateModelMixin

ListAPIView

用于只读端点,以表示模型实例集合

提供get方法处理程序。

扩展:GenericAPIViewListModelMixin

检索APIView

用于只读端点,以表示单个模型实例

提供get方法处理程序。

扩展:GenericAPIViewRetrieveModelMixin

销毁APIView

用于单个模型实例的仅删除端点。

提供delete方法处理程序。

扩展:GenericAPIViewDestroyModelMixin

UpdateAPIView

用于单个模型实例的仅更新端点。

提供putpatch方法处理程序。

扩展:GenericAPIViewUpdateModelMixin

ListCreateAPIView

用于读写端点,以表示模型实例集合

提供getpost方法处理程序。

扩展:GenericAPIViewListModelMixinCreateModelMixin

RetrieveUpdateAPIView

用于读取或更新端点以表示单个模型实例

提供getput并且patch方法处理。

扩展:GenericAPIViewRetrieveModelMixinUpdateModelMixin

RetrieveDestroyAPIView

用于读取或删除端点,以表示单个模型实例

提供getdelete方法处理程序。

扩展:GenericAPIViewRetrieveModelMixinDestroyModelMixin

RetrieveUpdateDestroyAPIView

用于读写删除端点,以表示单个模型实例

提供getputpatchdelete方法处理。

扩展:GenericAPIViewRetrieveModelMixinUpdateModelMixinDestroyModelMixin


自定义通用视图

通常,您将需要使用现有的通用视图,但是会使用一些稍微自定义的行为。如果发现自己在多个地方重复使用了一些自定义行为,则可能需要将行为重构为一个通用类,然后可以根据需要将其仅应用于任何视图或视图集。

创建自定义混合

例如,如果您需要基于URL conf中的多个字段查找对象,则可以创建如下的mixin类:

  1. class MultipleFieldLookupMixin:
  2. """
  3. Apply this mixin to any view or viewset to get multiple field filtering
  4. based on a `lookup_fields` attribute, instead of the default single field filtering.
  5. """
  6. def get_object(self):
  7. queryset = self.get_queryset() # Get the base queryset
  8. queryset = self.filter_queryset(queryset) # Apply any filter backends
  9. filter = {}
  10. for field in self.lookup_fields:
  11. if self.kwargs[field]: # Ignore empty fields.
  12. filter[field] = self.kwargs[field]
  13. obj = get_object_or_404(queryset, **filter) # Lookup the object
  14. self.check_object_permissions(self.request, obj)
  15. return obj

然后,您可以在需要应用自定义行为的任何时间简单地将此mixin应用于视图或视图集。

  1. class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
  2. queryset = User.objects.all()
  3. serializer_class = UserSerializer
  4. lookup_fields = ['account', 'username']

如果您需要使用自定义行为,则使用自定义混合是一个不错的选择。

创建自定义基类

如果要在多个视图之间使用混合,则可以更进一步,并创建自己的基础视图集,然后将其用于整个项目。例如:

  1. class BaseRetrieveView(MultipleFieldLookupMixin,
  2. generics.RetrieveAPIView):
  3. pass
  4. class BaseRetrieveUpdateDestroyView(MultipleFieldLookupMixin,
  5. generics.RetrieveUpdateDestroyAPIView):
  6. pass

如果您的自定义行为始终需要在整个项目中的大量视图中重复进行,则使用自定义基类是一个不错的选择。


放置为创建

在3.0版之前PUT,取决于对象是否存在,REST框架混合将其视为更新或创建操作。

允许PUT作为创建操作是有问题的,因为它必然会公开有关对象存在或不存在的信息。与仅返回404响应相比,透明地允许重新创建先前删除的实例必然是更好的默认行为,这也不是显而易见的。

PUTas 404”和“ PUTas create”这两种样式在不同情况下都可以有效,但是从3.0版开始,由于它更简单,更明显,现在我们将404行为用作默认行为。

如果需要通用的PUT即创建行为,则可能需要将此类之AllowPUTAsCreateMixin类的内容作为混合添加到视图中。


第三方套餐

以下第三方软件包提供了其他通用视图实现。

Django Rest多种模型

Django Rest Multiple Models提供了通用视图(和混合),用于通过单个API请求发送多个序列化的模型和/或查询集。