django rest framework 中的三种视图写法

一、基本视图类 (APIView/@api_view)

1、类基础视图(APIView)

DRF不同于django常规的view类,他有如下几点优点:
* 提供了更好用的request对象,不同于普通的django HttpRequest更好用。
* 封装了Response对象,代替了原有的django HttpResponse,视图将管理内容协商并设置正确的渲染器的响应。
* 任何APIException异常将会被捕捉,并做适当的响应。
* 传入的请求将身份验证和适当的权限和节流检查将之前运行调度请求处理程序的方法。
一个小例子:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authenication, permissions

class ListUser(APIView):
“””

展示系统中所有的用户
* 需要令牌认证。
* 只有admin用户能够访问这一个视图

"""
authentication_classes = (authentication.TokenAuthentication,)  # 认证策略属性
permission_classes = (permissions.IsAdminUser,) # 权限策略属性

def get(self, requeset, format=None):
"""
返回一个用户列表
"""
usernames = [user.username for user in  User.objects.all()]
return Response(usernames)
1) API策略属性

以下的API策略属性应用于APIView,控制视图的策略:
renderer_classes: 渲染器类
parser_classes: 解释器类
authentication_classes: 权限类
throttle_classes:节流类
permission_classes: 权限类
content_negotiation_class: 内容协商类

2)API 策略方法

以下的策略方法用在API的策略,通常不用重写它:
get_renderers(self): 获取渲染器方法
get_parsers(self): 获取解释器方法
get_authenticators(self): 或缺认证方法
get_throttles(self): 获取节流方法
get_permissions(self): 获取权限方法
get_content_negotiator(self): 获取内容协商方法

3)API策略实施方法

下列方法之前被称为调度处理程序方法:
check_permissions(self, request): 检查权限
check_throttles(self, request): 检查节流
check_content_negotiation(self, request, force=False): 检查内容协商

4)调度方法

这些执行任何操作,需要发生之前或之后调用处理程序方法等.
initial(self, request, *args, **kwargs): 执行任何操作,需要发生在处理程序方法之前被调用。这个方法是用来执行权限和节流,并执行内容协商。
handle_exception(self, exc):抛出的任何异常处理程序方法将被传递给这个方法,而返回响应实例,或者re-raises异常。
initialize_request(self, request, *args, **kwargs):确保请求对象传递给处理程序方法是request的一个实例,而不是django的HttpRequest
finalize_response(self, request, response, *args, **kwargs):确保任何响应处理程序方法返回的对象将被呈现到正确的内容类型

2、函数基础视图(@api_view())

DRF同样提供了另外一种函数基础视图来装饰django的普通视图,我们同样可以使用request来接受请求和response响应。
一个小例子:

from rest_framework.decorators import api_view

@api_view
def hello_world(request):
return Response({“message”:”Hello world!”})
1)api_view()使用方法

这个视图将使用默认渲染器、解析器、身份验证设置中指定的类等。通常默认只有GET方法,其他请求方法会报405错误,我们可以手动添加方法为这
装饰器指定request方法。像这样:

@api_view([‘GET’, ‘POST’])
def hello_world(request):
if request.method  == ‘POST’:
return Response({“message”:”Got some data”, “data”: request.data})
return Response({“messsage”:”Hello world!”})
2)API策略装饰器

DRF提供了很多附加的装饰器,我们可以添加到@api_view()后面,例如要加入一个节流的装饰器来确保特定用户每天只能一次通过这个视图,我
我们就要用到@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 to day! see you tomorrow!”})

其他可用API的装饰器:
@renderer_classes(…)
@parser_classes(…)
@authentication_classes(…)
@throttle_classes(…)
@permission_classes(…)

二、 通用视图(Generic views)

基于类视图的主要好处之一是他们允许您编写可重用的行为.
REST框架提供的通用视图允许您快速构建API观点紧密地映射到您的数据库模型.
如果通用视图不适合你的需要API,您可以使用常规APIView类,或重用mixin和基类使用的通用视图来组成自己的组可重用通用视图。

1、通用视图

同样我们可以设置一些类属性在通用视图内,也可以根据特殊要写重写它的内部视图方法。一个小例子:

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,)

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)

在urls配置中,我们可以使用.as_views()来转换成视图函数,当然也可以配置一些属性

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

2、GenericAPIView通用视图API参考:

GenericAPIView继承了DRF的APIView类,为list和detail视图增加了一些一般需求行为方法(提供queryset)。

1)属性

基本属性:
queryset: 用于返回query对象集合,也可以使用get_queryset()方法。
serializer_class: 序列化器类,应该用于输入进行验证和反序列化,并用于序列化输出。通常情况下,你必须设置这个属性,或重写get_serializer_class()方法。
lookup_field: 模型的字段应该用于执行对象查找个别的模型实例
lookup_url_kwarg:URL应该用于对象查找关键字参数

分页属性:
pagination_class: 用于返回一个分页列表视图的分页类,默认与settings中设置的DEFAULT_PAGINATION_CLASS 值相同,
可以通过’rest_framework.pagination.PageNumberPagination’设置分页数
过滤器属性:
filter_backends: 过滤queryset的类列表,和在settings中设置DEFAULT_FILTER_BACKENDS 一样

2)方法

基本方法:
get_queryset(): 返回queryset。(详情见官网http://www.django-rest-framework.org/api-guide/generic-views/
get_object():获取某一个具体的model实例对象。
保存与删除挂钩方法:
以下方法是mixins类提供,提供简单的对象保存和删除的行为重写:
perform_create(self, serializer): CreateModelMixin 当要保存对象时候会被调用
perform_update(self, serializer):UpdateModelMixin 当要更新对象时候会被调用
perform_destroy(self, instance): DestoryModelMixin 当药删除对象时候会被调用

3)、Mixins

mixin类提供用于提供基础视图的操作行为。注意,mixin类提供操作方法而不是定义处理程序方法,比如. get()和. post(),直接。这允许更灵活的组合的行为。
通过rest_framework.mixins引用。
ListModelMixin:提供list方法,列出queryset
CreateModelMixin: 提供create方法,创建和保存一个Model对象
RetrieveModelMixin:提供retrieve方法,检索一个存在的model对象
UpdateModelMixin: 提供Update方法,更改一个模型对象
DestroyModelMixin:提供destroy方法,删除一个模型对象

4)Generic

Generic通用视图类提供具体操作的通用视图类,可以理解为Generic.GenericAPIView和mixin类的合体,通过rest_framework.generic.调用

.CreateAPIView:

创建一个模型实例
提供post方法的处理器
继承于:GenericAPIView,CreateModelMixin

.ListAPIView:

模型实例的集合
提供get方法处理器
继承于:GenericAPIView,ListModelMixin

.RetrieveAPIView:

一个模型实例
提供get方法处理器
继承于:GenericAPIView,RetrieveModelMixin

.DestoryAPIView:

删除一个模型实例
提供delete方法处理器
继承于:GenericAPIView,DestroyModelMixin

.UpdateAPIView:

修改模型实例,
提供put和patch方法处理器
继承于:GenericAPIView,UpdateModelMixin

.ListCreateAPIView:

创建和展示一个模型实例集合
提供get和post处理器
继承于:GenericAPIView,ListModelMixin,CreateModelMixin

.RetrieveUpdateAPIView:

读和改一个模型实例
提供get,put,patch处理器
继承于:GenericAPIView,RetrieveModelMixin,UpdateModelMixin

.RetrieveDestoryAPIView:

读和删除一个模型实例
提供get和delete处理器
继承于:GenericAPIView,RetrieveModelMixin,DestroyModelMixin

.RetrieveUpdateDestroyAPIView:

读、改和删一个模型实例
get, put, patch,delete处理器
继承于:GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin

三、视图集合ViewSets

Django REST框架允许您将一组相关的逻辑视图在一个类,ViewSet类是一个简单类型的基于类的观点,没有提供任何方法处理程序如.get()或. post(),
而代替提供方法比如.list()和create()。
一个小例子:

from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from myapps.serializers import UserSerializer
from rest_framework import viewsets
from rest_framework.response import Response

class UserViewSet(viewsets.ViewSet):
“””
A simple ViewSet for listing or retrieving users.
“””
def list(self, request):
queryset = User.objects.all()
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)

def retrieve(self, request, pk=None):
queryset = User.objects.all()
user = get_object_or_404(queryset, pk=pk)
serializer = UserSerializer(user)
return Response(serializer.data)

1).关于ViewSets

如果我们需要,我们需要为两个GET请求分开绑定视图:
user_list = UserViewSet.as_view({“GET”:’list’})
user_detail = UserViewSet.as_view({‘GET’:’retrieve’})

但是通常我们不会这样做,而是通过注册路由来配置url:

from myapp.views import UserViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r’users’, UserViewSet)
urlpatterns = router.urls

或许你会经常用到自己模型数据,而不是手动写视图集合,这样就要用到模型视图集合ModelViewSet:

class UserViewSet(viewsets.ModelViewSet):
“””
A viewset for viewing and editing user instance
“””
serializer_class = UserSerializer
queryset = User.objects.all()

其他路由函数方法:

class UserViewSet(viewsets.ViewSet):
“””
Example empty viewset demonstrating the standard
actions that will be handled by a router class.

If you’re using format suffixes, make sure to also include
the format=None keyword argument for each action.
“””

def list(self, request):
pass

def create(self, request):
pass

def retrieve(self, request, pk=None):
pass

def update(self, request, pk=None):
pass

def partial_update(self, request, pk=None):
pass

def destroy(self, request, pk=None):
pass
如果你有特别的需要被路由到的方法,可以将它们标记为需要路由使用@detail_route或@list_route修饰符。
@detail_route(methods=[‘post’], permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
…
可以通过访问^users/{pk}/set_password/$来访问改视图

2)ViewSets的API参考

.ViewSet:

继承了APIView,你可以使用一些标准的属性例如permission_class,authentication_classes去对视图做一些策略。ViewSet同样不提供具体
行为方法的实现,你可以重写和定义一些请求处理方法。而代替了原来APIVIew的POST,GET等方法,取而代之的是list,create等方法。

.GenericViewSet:

继承了GenericAPIView,提供了默认的get_queryset()和get_object()等方法来获取model数据,但不提供任何请求处理方法。

.ModelViewSet:

继承了GenericAPIView,增加了一些请求处理方法,如list(), retrieve(),create()等。

例子:

class AccountViewSet(viewsets.ModelViewSet):
“””
A simple ViewSet for viewing and editing accounts
“””
queryset = Account.objects.all()
serializer_class = AccountSerializer
permissions_classes = [IsAccountAdminOrReadOnly]
.ReadOnlyModelViewSet:

继承了GenericAPIView,只增加了只读的请求处理方法list()和retrieve()

自定义View类:

只需要继承GenericAPIView, 增加mixins的相关处理方法。如:

class CreatListRetrieveViewSet(mixins.CreateModelMixin,
mixins.ListModelMixin,
mixins.RetrieveModelMixin,
View.GenericViewSet):
pass
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342