API Guide(四)之Generic views

通用的视图

Django’s generic views... were developed as a shortcut for common usage patterns... 它们采取一些常见的习语和模式,在视图开发中创建并抽象,以便可以快速编写数据的常见视图,而无需重复。

Django文档

CBV的主要优点之一是 the way they allow you to compose bits of reusable behavior. REST framework takes advantage of this by providing a number of pre-built views that provide for commonly used patterns.

REST框架提供的通用视图允许您快速构建与数据库模型紧密对应的API视图。

如果通用视图不符合您的API需求,你可下拉到使用常规APIView 类,或者重用通用视图所使用的mixins和base类来构建一组您自己的可重用通用视图。

例子

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

from django.contrib.auth.models import User
from myapp.serializers import UserSerializer
from rest_framework import generics
from rest_framework.permissions import IsAdminUser

class UserList(generics.ListCreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsAdminUser,)

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

class UserList(generics.ListCreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsAdminUser,)

    def list(self, request):
        # Note the use of `get_queryset()` instead of `self.queryset`
        queryset = self.get_queryset()
        serializer = UserSerializer(queryset, many=True)
        return Response(serializer.data)

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

url(r‘^/users/‘, ListCreateAPIView.as_view(queryset=User.objects.all(), serializer_class=UserSerializer), name=‘user-list‘)

API参考

GenericAPIView

这个类扩展了REST框架的APIView类,为标准列表和详细视图添加了常见的行为。

提供的每个具体的通用视图都是通过把GenericAPIView与一个或多个mixin类进行组合来构建的。

属性

基本设置

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

  • queryset - 用于从此视图返回对象的查询器。通常,您必须设置此属性,或覆盖get_queryset()方法。如果您覆盖了一个视图方法,那么重要的是调用get_queryset()而不是直接访问此属性,as queryset will get evaluated once, and those results will be cached for all subsequent requests.
  • serializer_class - 用于对输入进行验证和反序列化以及对输出进行序列化。通常,您必须设置此属性,或覆盖get_serializer_class()方法。
  • lookup_field - 用于执行个别模型实例的对象查找的模型字段。默认为‘pk‘。请注意,当使用超链接的API时,如果你需要使用一个自定义值,那么需要确保the API views and the serializer classes 都设置了查找字段。
  • 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 属性指定的queryset。

应始终使用此方法,而不是直接访问self.queryset,因为self.queryset每执行一次,就会为所有后续请求缓存这些结果。

可能会被覆盖以提供动态行为,such as returning a queryset, that is specific to the user making the request.

例如:

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

get_object(self)

返回应用于详细视图的对象实例。默认使用lookup_field参数过滤 the base queryset。

可能会被覆盖以提供更复杂的行为,例如基于多个URL kwarg的对象查找。

例如:

def get_object(self):
    queryset = self.get_queryset()
    filter = {}
    for field in self.multiple_lookup_fields:
        filter[field] = self.kwargs[field]

    obj = get_object_or_404(queryset, **filter)
    self.check_object_permissions(self.request, obj)
    return obj

请注意,如果您的API不包括任何对象级别的权限,您可以选择性地排除self.check_object_permissions,只从get_object_or_404查找返回对象。

filter_queryset(self, queryset)

给定一个 queryset,使用任何 filter backends 进行过滤,返回一个新的 queryset。

例如:

def filter_queryset(self, queryset):
    filter_backends = (CategoryFilter,)

    if ‘geo_route‘ in self.request.query_params:
        filter_backends = (GeoRouteFilter, CategoryFilter)
    elif ‘geo_point‘ in self.request.query_params:
        filter_backends = (GeoPointFilter, CategoryFilter)

    for backend in list(filter_backends):
        queryset = backend().filter_queryset(self.request, queryset, view=self)

    return queryset

get_serializer_class(self)

返回用于序列化的类。默认返回serializer_class属性。

可能会被覆盖以提供动态行为,例如使用不同的 serializers 进行读写操作,或者为不同类型的用户提供不同的 serializers 。

例如:

def get_serializer_class(self):
    if self.request.user.is_staff:
        return FullAccountSerializer
    return BasicAccountSerializer

保存和删除 hooks

以下方法由mixin类提供,并提供容易地覆盖对象保存或删除行为。

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

这些钩子特别适用于设置请求中隐含的属性,但不是请求数据的一部分。例如,您可以根据请求用户或基于URL关键字参数在对象上设置属性。

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

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

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

您还可以使用这些钩子来提供额外的验证ValidationError()。如果您需要在数据库保存时应用一些验证逻辑,这将非常有用。例如:

def perform_create(self, serializer):
    queryset = SignupRequest.objects.filter(user=self.request.user)
    if queryset.exists():
        raise ValidationError(‘You have already signed up‘)
    serializer.save(user=self.request.user)

注意:这些方法取代旧式的2.x版pre_savepost_savepre_deletepost_delete方法,这将不再可用。

其他方法

通常您不需要重写以下方法,尽管如果您使用自定义视图编写自定义视图,则可能需要调用它们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则将返回响应,错误详细信息作为响应的正文。

RetrieveModelMixin

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

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

UpdateModelMixin

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

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

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

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

DestroyModelMixin

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

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


混凝土视图类

以下类是具体的通用视图。如果您使用通用视图,这通常是您将要工作的级别,除非您需要大量定制的行为。

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

CreateAPIView

用于仅创建端点。

提供一个post方法处理程序。

扩展:GenericAPIViewCreateModelMixin

ListAPIView

用于只读端点来表示模型实例的集合

提供一个get方法处理程序。

扩展:GenericAPIViewListModelMixin

RetrieveAPIView

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

提供一个get方法处理程序。

扩展:GenericAPIViewRetrieveModelMixin

DestroyAPIView

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

提供一个delete方法处理程序。

扩展:GenericAPIViewDestroyModelMixin

UpdateAPIView

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

提供putpatch方法处理程序。

扩展:GenericAPIViewUpdateModelMixin

ListCreateAPIView

用于读写端点来表示模型实例的集合

提供getpost方法处理程序。

扩展:GenericAPIViewListModelMixinCreateModelMixin

RetrieveUpdateAPIView

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

提供getput并且patch方法处理。

扩展:GenericAPIViewRetrieveModelMixinUpdateModelMixin

RetrieveDestroyAPIView

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

提供getdelete方法处理程序。

扩展:GenericAPIViewRetrieveModelMixinDestroyModelMixin

RetrieveUpdateDestroyAPIView

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

提供getputpatchdelete方法处理。

扩展:GenericAPIViewRetrieveModelMixinUpdateModelMixinDestroyModelMixin


自定义通用视图

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

创建自定义混音

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

class MultipleFieldLookupMixin(object):
    """
    Apply this mixin to any view or viewset to get multiple field filtering
    based on a `lookup_fields` attribute, instead of the default single field filtering.
    """
    def get_object(self):
        queryset = self.get_queryset()             # Get the base queryset
        queryset = self.filter_queryset(queryset)  # Apply any filter backends
        filter = {}
        for field in self.lookup_fields:
            if self.kwargs[field]: # Ignore empty fields.
                filter[field] = self.kwargs[field]
        return get_object_or_404(queryset, **filter)  # Lookup the object

只要您需要应用自定义行为,您可以简单地将此mixin应用于视图或视图。

class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    lookup_fields = (‘account‘, ‘username‘)

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

创建自定义基类

如果您在多个视图中使用mixin,您可以进一步了解并创建自己的一组基本视图,然后可以在整个项目中使用。例如:

class BaseRetrieveView(MultipleFieldLookupMixin,
                       generics.RetrieveAPIView):
    pass

class BaseRetrieveUpdateDestroyView(MultipleFieldLookupMixin,
                                    generics.RetrieveUpdateDestroyAPIView):
    pass

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


PUT作为创建

在版本3.0之前,REST框架mixin被PUT视为更新或创建操作,具体取决于对象是否已存在。

允许PUT作为创建操作是有问题的,因为它必然暴露关于对象的存在或不存在的信息。透明地允许重新创建先前删除的实例也不是一个更好的默认行为,而不仅仅是返回响应也不是很404明显。

两种样式“ PUT404”和“ PUT创建”可以在不同的情况下有效,但是从3.0版起,我们现在使用404行为作为默认,因为它更简单和更明显。

如果需要通用PUT,为创建行为,你可能要包括像这个AllowPUTAsCreateMixin的混入你的意见。


第三方包

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

Django REST Framework批量

Django的REST的架构,散包实现通用视图混入以及一些普通混凝土通用视图允许通过API请求应用批量操作。

Django Rest多个模型

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

时间: 2024-08-24 08:33:44

API Guide(四)之Generic views的相关文章

Django REST Framework API Guide 03

本节大纲 1.Routers 2.Parsers 3.Renderers Routers Usage from rest_framework import routers router = routers.SimpleRouter() router.register(r'users', UserViewSet) router.register(r'accounts', AccountViewSet) urlpatterns = router.urls register的两个必填参数prefix,

【高德地图API】从零开始学高德JS API(四)搜索服务

摘要:地图服务,大家能想到哪些?POI搜素,输入提示,地址解析,公交导航,驾车导航,步行导航,道路查询(交叉口),行政区划等等.如果说覆盖物Marker是地图的骨骼,那么服务,就是地图的气血.有个各种各样的地图服务,我们的地图应用才能变得有血有肉,活灵活现.第四篇拆成了几个要点,本篇主要讲搜索服务.包括周边搜索,关键词搜索,范围搜索,搜索提示(自动完成,输入提示),行政区域,交叉路口,检索自有数据(云图). demo:http://zhaoziang.com/amap/zero_4_1.html

HOOK API(四)—— 进程防终止

HOOK API(四) —— 进程防终止 0x00        前言 这算是一个实战吧,做的一个应用需要实现进程的防终止保护,查了相关资料后决定用HOOK API的方式实现.起初学习HOOK API的起因是因为要实现对剪切板的监控,后来面对进程保护这样一个需求时,综合各方资料并自己动手实现HOOK OpenProcess() 和 TerminateProcess() 来从调用层实现进程的防终止.下面将进一步介绍实现的过程,也算是对学习的一个总结与实战. 主要参考:http://www.cnbl

【高德地图API】从零开始学高德JS API(四)搜索服务——POI搜索|自动完成|输入提示|行政区域|交叉路口|自有数据检索

摘要: 地图服务,大家能想到哪些?POI搜素,输入提示,地址解析,公交导航,驾车导航,步行导航,道路查询(交叉口),行政区划等等.如果说覆盖物Marker是地图的骨骼,那么服务,就是地图的气血.有个各种各样的地图服务,我们的地图应用才能变得有血有肉,活灵活现. 第四篇拆成了几个要点,本篇主要讲搜索服务.包括周边搜索,关键词搜索,范围搜索,搜索提示(自动完成,输入提示),行政区域,交叉路口,检索自有数据(云图). demo:http://zhaoziang.com/amap/zero_4_1.ht

minSdkVersion、targetSdkVersion、maxSdkVersion、target API level四个数值到底有什么区别

在AndroidMenifest.xml中,常常会有下面的语句: <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="10" android:maxSdkVersion="10" /> 在default.properties中,会看到下面的语句: target=android-10 如果是使用Eclipse的话,还可能会看到这样的警告:Attribute minS

使用 ASP.NET Core MVC 创建 Web API(四)

原文:使用 ASP.NET Core MVC 创建 Web API(四) 使用 ASP.NET Core MVC 创建 Web API 使用 ASP.NET Core MVC 创建 Web API(一) 使用 ASP.NET Core MVC 创建 Web API(二) 使用 ASP.NET Core MVC 创建 Web API(三) 十三.返回值 在上一篇文章(使用 ASP.NET Core MVC 创建 Web API(二))中我们创建了GetBookItems和 GetBookItem两

Django-简述generic views

Use generic views: Less code is better. These views represent a common case of basic Web development: getting data from the database according to a parameter passed in the URL, loading a template and returning the rendered template. Because this is s

API Guide(三)之Views

Class-based Views Django's class-based views are a welcome departure from the old-style views. - Reinout van Rees REST框架提供了一个APIView类,which subclasses Django's View class. APIView类与普通View类有以下不同: 传递给the handler methods 的Requests 将是REST框架的Request实例,而不是

API Guide(十四)之Permissions

权限 身份验证或身份识别本身通常不足以获取信息或代码的访问权限.为此,请求访问的实体必须具有授权. - 苹果开发者文档 连同认证和限制,权限决定是否应该授予请求或拒绝访问. 在允许继续执行任何其他代码之前,权限检查始终在视图的开始处运行.权限检查通常将使用在所述认证信息request.user和request.auth属性,以确定是否输入请求应该被允许. 权限用于授予或拒绝将不同类别的用户访问到API的不同部分. 最简单的权限是允许访问任何经过身份验证的用户,并拒绝访问任何未经身份验证的用户.这