Django-restframework12 Generic views
来源:互联网 发布:伊丽莎白雅顿天猫 知乎 编辑:程序博客网 时间:2024/04/29 21:21
1.引语
Django的通用视图已经发展成一种常见的使用模式的快捷方式,他们采取在视图开发中发现一些常见习语和模式,并将其抽象出来,以便于可以快速编写数据的常见视图,而不需要重复编写。
2.简介
- 基于类的视图允许自由设计组合可重用的模式,REST框架通过提供许多常用模式的预构建视图来利用这一点,如RETIRVEUPDATEAPIVIEW等
- REST提供的通用视图可以快速构建与数据库模型紧密对应的API视图
- 如果通用视图不满足需求,可以使用常规APIView,然后自由组合各种Mixin类,来构建自己的使用模式
3.使用示例
如果使用通用视图类,意味着你需要重写视图函数和几个类属性。
from django.contrib.auth.models import Userfrom myapp.serializers import UserSerializerfrom rest_framework import genericsfrom rest_framework.permissions import IsAdminUserclass 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()函数,只需要传入相应的参数就行
url(r'^/users/', ListCreateAPIView.as_view(queryset=User.objects.all(), serializer_class=UserSerializer), name='user-list')
4.GenericAPIView
继承了REST框架的APIView,为标准list添加了一些行为和具体的视图
其他的通用视图,都是由GenericAPIView结合一个或多个Mixin类扩展而成
属性
基本设置:
- queyset
查询集,用于返回查询对象,一般你必须设置这个属性,或者重写get_queryset()方法。如果你重写了视图方法,就需要使用get_queryset()方法代替直接使用这个属性。因为queryset只会评估一次,然后就存入缓存cache中,以供后来的请求使用。 - serializer_class
serializer_class被用来验证和反序列化输入,序列化输出。一般来说,你要么设置这个属性,要么重写get_serializer_class()方法 - lookup_field
用于查找单个模型实例的模型字段,默认为’pk’
注意:当时用超链接API时,如果需要使用自定义字段,必须在API views和序列化类中都设置lookup_field值。 - lookup_url_kwarg
也是用于查找某个对象,但是url配置时,必须设置相应的值,如果没有设置默认值,那么默认使用lookup_field的值。
分页
- pagination_class
当需要分页显示获取的 list结果时使用。默认值与DEFAULT_PAGINATION_CLASS(’rest_framework.pagination.PageNumberPagination’)相同,设置pagination_class=None将会禁用分页功能。
过滤
- filter_backends
用于过滤查询集,默认值与DEFAULT_FILTER_BACKENDS设置值相同
方法
基本方法
- get_queryset(self)
返回查询集结果,是获取详细查询的基础。默认返回queryset属性指定的查询集结果
通常不是用于获取queryset,而是重写之后用于获取动态的查询集,如:
def get_queryset(self): user = self.request.user return user.accounts.all()
- get_object(self)
用于detail查询函数中,默认值是利用lookup_field参数过滤基础的queryset查询集
可以重写用于更加复杂的查询,例如在url链接中有多个查询参数的时候,如:
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
如果你的接口没有设置权限等级,self.check_object_permissions(self.request, obj)这一句就可以删除掉。
- filter_queryset(self, queryset)
通过提供一个查询集,然后根据设置的filter_backends进行过滤,然后返回一个新的查询集,如:
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): # backend(), view=self??? 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,删除一个存在的实例
这些钩子在为request设置隐性属性时 特别有用。例如,你可以为一个对象设置属性,基于请求的用户,或者基于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方法,它们不在能被使用。
其他方法
尽管你在编写定制化视图时需要调用它们,但是一般来说以下的方法不用重写
- get_serializer_context(self) : 包含一些需要额外提供给序列化器的上下文字典,默认包含’request’, ‘view’ 和 ‘format’;
- get_serializer(self, instance=None, data=None, many=False, partial=False):返回一个序列化实例;
- get_paginated_response(self, data):返回一个分好页的响应对象;
- paginate_queryset(self, queryset): 分页查询集,如果要求,则返回已分页的查询集对象,否则返回None;
- filter_queryset(self, queryset):如果设置了过滤类,那就返回过滤后的queryset对象,否则返回queryset。
5. Mixins
mixin类只是提供一些基础的视图操作,并没有定义处理函数,如.get() and .post()等,这样有便于灵活的组装这些操作
ListModelMixin
提供.list(request, *args, **kwargs)方法,如果获取到查询结果,就序列化为响应主体,选择性分页后,返回给用户一个200的响应对象
CreateModelMixin
提供.create(request, *args, **kwargs),用于创建,保存一个实例,如果对象创建成功就返回一个201 Created的对象,序列化之后作为响应主体,如果显示字段包含url,那么就用该值填充Location的header,如果数据不合法,就返回400 Bad Request响应对象,响应对象主体为错误的详细信息
RetrieveModelMixin
提供.retrieve(request, *args, **kwargs) 方法,实现返回一个数据库中已经存在的模型实例,返回200 OK response, 或者404 Not Found
UpdateModelMixin
提供.update(request, *args, **kwargs)方法,实现了更新并保存一个已经存在的实例(必须提供全部字段值)
.partial_update(request, *args, **kwargs) 部分更新,允许PATCH方法
返回200 OK response或者400 Bad Request response
DestroyModelMixin
提供了一个.destroy(request, *args, **kwargs)用于删除已经存在的模型实例
返回204 No Content response或者404 Not Found
6.复合视图类
- CreateAPIView: post+create
- ListAPIView: get + list
- RetrieveAPIView: get + retrieve
- DestroyAPIView: delete + destory
- UpdateAPIView: upadate + put + patch
- ListCreateAPIView: list + create + get + put + patch
- RetrieveDestroyAPIView: retrieve + destory + get + delete
- RetrieveUpdateDestroyAPIView: retreve + destroy + update + get + put + patch + delete
7.自定义通用视图
当你在通用视图基础上添加一些自定义的行为时,如果发现在许多地方都要使用此行为,你可以将其抽象成一个mixin类,哪里需要就添加到哪里!
比如说你利用从url中获取的多个参数来查询对象,你可以创建一个mixin类
# 创建一个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. """ # 重写get_object方法 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类时,你可以创建一个基础的APIView:
class BaseRetrieveView(MultipleFieldLookupMixin, generics.RetrieveAPIView): passclass BaseRetrieveUpdateDestroyView(MultipleFieldLookupMixin, generics.RetrieveUpdateDestroyAPIView): pass
8.使用PUT方法创造PUT as create or PUT as 404
在3.0之前,REST框架利用PUT方法根据对象是否存在进行created或者update。
利用PUT方法进行创建操作是有问题的,因为PUT肯定会暴露已存在和正在进行创建的对象信息
但是另一方面,允许创建已经删除的对象比默认的只是简单的返回一个404 Response更好。
PUT as create or PUT as 404这两种形式都是合法的,但是从3.X版本以后使用PUT as 404作为默认值,因为其更加简单而且明显。
如果想使用PUT as create,你可以在创建视图类时,使用AllowPUTAsCreateMixin类。
9.第三方包
- Django REST Framework bulk
实现了一些mixin类,和一些扩展的复合视图类 - Django Rest Multiple Models
允许在一个API视图中返回多个序列化模型
- Django-restframework12 Generic views
- Django笔记-generic views
- Django笔记-generic views
- django - generic views
- django使用通用视图 django.views.generic
- django的通用视图 (generic views)
- Django generic.Views 源码初步剖析
- Generic Views
- Django学习笔记之:【通用视图 (generic views) 】
- 千与千寻django(六)---通用视图(Generic views)
- Django rest framework API Guide的 Generic views 翻译
- Django REST framework-API指南04-Generic views 原创翻译
- 读书笔记:Django 模板开发(二)Views, URLs, and Generic Views
- python_Django_4:Forms and generic views
- Django generic view
- Django Generic Display View
- Django笔记-URLConf Views
- Django笔记-URLConf Views
- 第九周项目三(2) 求叶节点
- 赛车类嵌入式小游戏《极限逆行》设计与实现
- linux netlink的使用及示例
- “十九大”风向标:行业结构转型,复合型人才薪资可观
- ELK研究(一):elasticsearch java api接口操作ES集群 ---TransportClient的使用介绍 bulk批量提交数据
- Django-restframework12 Generic views
- 实现依赖注入的多种方式
- 慕课网《HTML+CSS基础课程》笔记总结(七)
- 深度学习中的大牛
- leetcode 53. Maximum Subarray
- MySql中索引学习
- 【wxPython】wxPython获取系统字体
- 如何做卓有成效的程序员
- GDB跟踪调试linux-3.18.6内核