通用视图

Django的通用视图......被开发为常见用法模式的快捷方式......它们采用视图开发中的某些常见习语和模式并对其进行抽象,以便您可以快速编写数据的常用视图,而无需重复自己。

- Django文档

基于类的视图的一个主要好处是它们允许您组合可重用行为的方式。REST框架通过提供许多预先构建的视图来提供常用模式来利用这一点。

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

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

例子

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

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()而不是直接访问此属性,因为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只进行一次评估,并为所有后续请求缓存这些结果。

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

例如:

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

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

可以重写以提供更复杂的行为,例如基于多个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)
给定一个查询集,使用正在使用的任何过滤后端过滤它,返回一个新的查询集。

例如:

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属性。

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

例如:

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

保存和删除挂钩:

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_save,post_save,pre_delete和post_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方法处理程序。

扩展:GenericAPIView,CreateModelMixin

ListAPIView
用于只读端点以表示模型实例的集合。

提供get方法处理程序。

扩展:GenericAPIView,ListModelMixin

RetrieveAPIView
用于表示单个模型实例的只读端点。

提供get方法处理程序。

扩展:GenericAPIView,RetrieveModelMixin

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

提供delete方法处理程序。

扩展:GenericAPIView,DestroyModelMixin

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

提供put和patch方法处理程序。

扩展:GenericAPIView,UpdateModelMixin

ListCreateAPIView
用于读写端点以表示模型实例的集合。

提供get和post方法处理程序。

扩展:GenericAPIView,ListModelMixin,CreateModelMixin

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

提供get,put并且patch方法处理。

扩展:GenericAPIView,RetrieveModelMixin,UpdateModelMixin

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

提供get和delete方法处理程序。

扩展:GenericAPIView,RetrieveModelMixin,DestroyModelMixin

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

提供get,put,patch和delete方法处理。

扩展:GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin

自定义通用视图
通常,您会希望使用现有的通用视图,但使用一些略微自定义的行为。如果您发现自己在多个位置重复使用某些自定义行为,则可能需要将该行为重构为公共类,然后可以根据需要将其应用于任何视图或视图集。

创建自定义mixins
例如,如果您需要根据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]
obj = get_object_or_404(queryset, **filter) # Lookup the object
self.check_object_permissions(self.request, obj)
return obj

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

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

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

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

class BaseRetrieveView(MultipleFieldLookupMixin,generics.RetrieveAPIView):
pass class BaseRetrieveUpdateDestroyView(MultipleFieldLookupMixin,generics.RetrieveUpdateDestroyAPIView):
pass

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

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

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

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

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

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

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

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

Django-Rest framework中文翻译-generic-views的更多相关文章

  1. Django REST FrameWork中文教程2:请求和响应

    从这一点开始,我们将真正开始覆盖REST框架的核心.我们来介绍几个基本的构建块. 请求对象REST框架引入了Request扩展常规的对象HttpRequest,并提供更灵活的请求解析.Request对 ...

  2. Django REST framework 中文教程1:序列化

    建立环境 在我们做任何事情之前,我们将使用virtualenv创建一个新的虚拟环境.这将确保我们的包配置与我们正在开展的任何其他项目保持良好的隔离. virtualenv envsource env/ ...

  3. Django REST FrameWork中文教程3:基于类的视图

    我们也可以使用基于类的视图编写我们的API视图,而不是基于函数的视图.我们将看到这是一个强大的模式,允许我们重用常用功能,并帮助我们保持代码DRY. 使用基于类的视图重写我们的API 我们将首先将根视 ...

  4. Django-Rest framework中文翻译-Request

    REST framework的Request类扩展自标准的HttpRequest,增加了REST framework灵活的请求解析和请求验证支持. 请求解析 REST framework的Reques ...

  5. Django REST Framework API Guide 02

    本节大纲 1.Generic Views 2.ViewSets  1.Generic Views CBV的主要的一个优点就是极大的允许了对于代码的从用.自然,rest framework取其优势,提供 ...

  6. 《Django By Example》第一章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:本人目前在杭州某家互联网公司工作, ...

  7. 《Django By Example》第三章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:第三章滚烫出炉,大家请不要吐槽文中 ...

  8. 《Django By Example》第九章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者@ucag 注:哈哈哈,第九章终于来啦 ...

  9. 《Django By Example》第十二章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:第十二章,全书最后一章,终于到这章 ...

随机推荐

  1. 栗染-Jsp编码常见问题

    如图在我们新建一个jsp的时候想给自己的页面加一个中文就会出现如图所示的问题 遇到这种情况一般是选第二个或者 将<%@ page language="java" import ...

  2. bzoj 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生【dp】

    参考:http://hzwer.com/3917.html 好神啊 注意到如果分成n段,那么答案为n,所以每一段最大值为\( \sqrt{n} \) 先把相邻并且值相等的弃掉 设f[i]为到i的最小答 ...

  3. 一个简陋的个人小项目,也是个人第一个真正意义上的独立项目——Graph

    由来 我最早接触到图这个概念是在大二的离散数学当中图论相关的内容,当时是以著名的哥尼斯堡七桥问题引出图论的概念,现在依然记忆犹新(不过只是记得这个名字,具体的解题思路我重新温习了一下才想起来),当时也 ...

  4. $CF55D [数位DP]$

    题面 数位DP+状压. 首先,按照数位DP的基本套路,每个个位数的最小公倍数为2520,所以只用考虑模2520的情况.考虑一个DP.dp[i][j][k]表示当前是第i位,2~9的数的集合为j,模25 ...

  5. oracle 自定义类型 type / create type

    一:Oracle中的类型有很多种,主要可以分为以下几类: 1.字符串类型.如:char.nchar.varchar2.nvarchar2. 2.数值类型.如:int.number(p,s).integ ...

  6. TFS修改了工作区

    计算机修改名字后,更换了TFS工作区,但原工作区的有些文件忘记签入: 解决方案: 删除原工作区即可,实现:到TFS工作区 - “管理工作区”,选中“显示远程工作区”,找到原工作区,删除即可.

  7. 20 如何在C#中存一批数据,数组

    使用软件的一个重要原因,是因为软件可以帮我们重复处理很多事情.在前面我们已经讲到了循环.循环就是为了重复处理一个事情.那么我们有没有想过,我们要重复处理的一批数据怎么在程序里存放呢? 举个例子吧. 我 ...

  8. 什么是2MSL以及TIME_WAIT的作用

    TIME_WAIT主要是用来解决以下几个问题: 1)上面解释为什么主动关闭方需要进入TIME_WAIT状态中提到的: 主动关闭方需要进入TIME_WAIT以便能够重发丢掉的被动关闭方FIN包的ACK. ...

  9. 6.12---前提两个对象的成员必须一致,才能将有数据的对象将数据传给反射获取的对象conver(有数据对象,目标对象)

    //// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)/ ...

  10. (1)HTML声明与基础(已入垃圾筐)

    来自网站http://www.runoob.com/html/html-intro.html <!DOCTYPE/> 声明 Doctype=Document Type=文档类型说明 htt ...