一、APIView

APIView 直接继承 View(Django 内置的 View),也就是说 APIView 是最贴近原生 Django 的 View 的。

因此可定制程度高,根据请求方法不同执行不同的函数:

源码:

class APIView(View):

    # The following policies may be set at either globally, or per-view.
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
metadata_class = api_settings.DEFAULT_METADATA_CLASS
versioning_class = api_settings.DEFAULT_VERSIONING_CLASS # Allow dependency injection of other settings to make testing easier.
settings = api_settings schema = DefaultSchema() @classmethod
def as_view(cls, **initkwargs):
"""
Store the original class on the view function. This allows us to discover information about the view when we do URL
reverse lookups. Used for breadcrumb generation.
"""
...

使用方法

1、urls.py

from django.urls import path, re_path
from api.views import UserView urlpatterns = [
re_path('(?P<version>[v1|v2]+)/users/', UserView.as_view(), name='api_user'),
]

2、views.py

from django.shortcuts import render, HttpResponse
from rest_framework.views import APIView class UserView(APIView): def get(self, request, *args, **kwargs):
pass def post(self, request, *args, **kwargs):
pass

二、GenericViewSet

映射关系

GenericViewSet 在 URL 中采用映射的关系将请求方法于视图函数一一对应,具体如下图:

URL 参数与视图函数映射关系

参数 视图中方法 说明
get list 获取数据
post create 创建数据
get retrieve 获取单条数据
put update 更新
patch partial_update 局部更新
delete destroy 删除

当然你也可以定位别的函数名,比如更新使用 add,相应地视图中也要定义为 def add() pass

在使用时,URL 中对应了几组映射关系,相应地视图中也要重写相应函数/方法。


GenericViewSet 继承关系

GenericViewSet 继承 GenericAPIView

class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
"""
The GenericViewSet class does not provide any actions by default,
but does include the base set of generic view behavior, such as
the `get_object` and `get_queryset` methods.
"""
pass

GenericAPIView 中实现了以下方法,包括:获取数据源、序列化、分页等

使用时,我们只需定义传入数据源、序列化的类和分页的类即可:

from rest_framework.viewsets import GenericViewSet
from .serializers import TestSerializers
from rest_framework.pagination import PageNumberPagination class TestView(GenericViewSet):
queryset = models.Role.objects.all()
serializer_class = TestSerializers
pagination_class = PageNumberPagination def list(self, request, *args, **kwargs):
# 获取数据
roles = self.get_queryset() # 分页
pager_roles = self.paginate_queryset(roles) # 序列化
roles_ser = self.get_serializer(instance=pager_roles, many=True) return Response(roles_ser.data) def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
# 验证用户输入的数据是否合法
serializer.is_valid(raise_exception=True)
# 合法则保存
serializer.save() # headers
# headers = self.get_success_headers(serializer.data) # 创建成功则返回刚刚创建的数据
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])} # URL_FIELD_NAME:url
except (TypeError, KeyError):
return {}

其中 get_queryset()paginate_queryset()get_serializer() 都是 GenericViewSet 实现的方法,直接调用即可。


如果你嫌每次还要写 list、create、delete 等方法,也可以直接继承 mixins.ListModelMixin、 mixins.CreateModelMixin、mixins.DestroyModelMixin ,其内部以及帮你实现了增删改查等功能,使用时只需继承即可。

from rest_framework.viewsets import GenericViewSet
from .serializers import TestSerializers
from rest_framework.pagination import PageNumberPagination
from rest_framework import mixins class TestView(mixins.ListModelMixin, mixins.CreateModelMixin, GenericViewSet):
# 只需将数据源于序列化的类和分页类赋值即可
queryset = models.Role.objects.all()
serializer_class = TestSerializers
pagination_class = PageNumberPagination

源码分析

ListModelMixin 来看,是不是和我们之前自定义的 list 做的事一样,同样地它也是实现了查询数据、序列化和分页的功能:

class ListModelMixin(object):
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)

更多源码可参考:rest_framework/mixins.py


参考

1、urls.py

from django.urls import path, re_path
from api.views import TestView urlpatterns = [
re_path('(?P<version>[v1|v2]+/test/)', TestView.as_view({'get': 'list', 'post': 'create'})),
]

2、models.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework import viewsets
from rest_framework.response import Response class TestView(viewsets.GenericViewSet):
def list(self, request, *args, **kwargs):
return Response('...') def add(self, request, *args, **kwargs):
pass # def delete(self, request, *args, **kwargs):
# pass # def edit(self, request, *args, **kwargs):
# pass


权限

class GenericAPIView(views.APIView):
"""返回请求的对象"""
def get_object(self):
...
# May raise a permission denied
self.check_object_permissions(self.request, obj)
...
pass
def check_object_permissions(self, request, obj):
"""
Check if the request should be permitted for a given object.
Raises an appropriate exception if the request is not permitted.
检查是否应该允许给定对象的请求。
    如果不允许请求,则引发适当的异常。
"""
for permission in self.get_permissions():
if not permission.has_object_permission(request, self, obj):
self.permission_denied(
request, message=getattr(permission, 'message', None)
)

三、ModelViewSet

ModelViewSet 是目前 rest_framework 中最高级别的 View,它继承了:

class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
"""
A viewset that provides default `create()`, `retrieve()`, `update()`,
`partial_update()`, `destroy()` and `list()` actions.
"""
pass

因此只要继承 ModelViewSet 即可完成增删改查。

1、urls.py

from django.urls import path, re_path
from api.views import TestView, TestView1 urlpatterns = [
re_path('(?P<version>[v1|v2]+/test/)', TestView.as_view({'get': 'list', 'post': 'create'})), re_path('(?P<version>[v1|v2]+/test1/)', TestView1.as_view({'get': 'list', 'post': 'create'})), # re_path('(?P<version>[v1|v2]+/test1/(?P<pk>\d+)/)', TestView1.as_view({'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'})),
]

2、views.py

from rest_framework.viewsets import GenericViewSet
from .serializers import TestSerializers
from rest_framework.pagination import PageNumberPagination
from rest_framework.viewsets import ModelViewSet class TestView1(ModelViewSet):
queryset = models.Role.objects.all()
serializer_class = TestSerializers
pagination_class = PageNumberPagination

四、总结

  • 如果想快速实现增删改查:ModelViewSet
  • 增删:CreateModelMixinDestroyModelMixinGenericViewSet
  • 复杂逻辑:GenericViewSetAPIView

rest framework 之视图的更多相关文章

  1. Django Rest framework 之 视图

    RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...

  2. Django rest framework (视图类详解)

    官网:https://www.django-rest-framework.org/api-guide/viewsets/ 在django rest framework 视图中一共有N个类 第一类:AP ...

  3. DRF Django REST framework 之 视图组件(四)

    引言 在我们有几十上百的视图类,都有get,post等方法,在功能类似时,会导致大量的重复代码出现,显然还有很多可以优化的地方.这也就有了视图组件,它的功能非常强大,能很好的优化接口逻辑. 视图组件 ...

  4. rest framework之视图组件

    一.APIView  APIView继承的是和django中CBV模式下的View类.View类中的dispatch方法通过反射对不同的请求方法执行不同的函数.而APIView不仅拥有这个特性,而且重 ...

  5. Django rest framework(8)---- 视图和渲染器

    django rest framework 之视图 序列化器    PagerSerialiser from rest_framework import serializers from api im ...

  6. Django REST framework 中的视图

    1.Request REST framework传入视图的request对象不再是Django默认的Httprequest对象,而是DRF提供的扩展类的Request类的对象 常用属性 request ...

  7. django的rest framework框架——分页、视图、路由、渲染器

    一.rest framework的分页 1.使用rest framework内置类PageNumberPagination实现分类 from django.conf.urls import url f ...

  8. Django 学习之Rest Framework 视图相关

    drf除了在数据序列化部分简写代码以外,还在视图中提供了简写操作.所以在django原有的django.views.View类基础上,drf封装了多个子类出来提供给我们使用. Django REST ...

  9. iOS 系统架构 && 常用 framework

    整理自互联网,感谢原文作者! 1.iOS基于UNIX系统,因此从系统的稳定性上来说它要比其他操作系统的产品好很多 2.iOS的系统架构分为四层,由上到下一次为:可触摸层(Cocoa Touch lay ...

随机推荐

  1. Makefile之编译运行连接库方法

    LIBS+= -L $$PWD/../HKUnifyCamera_one/Debug -lHKUnifyCamera -luuid -Wl,-rpath=$$PWD/../HKUnifyCamera_ ...

  2. 转载:EM算法的最精辟讲解

    机器学习十大算法之一:EM算法.能评得上十大之一,让人听起来觉得挺NB的.什么是NB啊,我们一般说某个人很NB,是因为他能解决一些别人解决不了的问题.神为什么是神,因为神能做很多人做不了的事.那么EM ...

  3. Biorhythms(信息学奥赛一本通 1639)

    题目描述: 人生来就有三个生理周期,分别为体力.感情和智力周期,它们的周期长度为23天.28天和33天.每一个周期中有一天是高峰.在高峰这天,人会在相应的方面表现出色.例如,智力周期的高峰,人会思维敏 ...

  4. DJI Terra+EasyEarth让数据获取与应用无缝衔接

    大数据时代对地理信息数据的获取与应用提出了更高的要求: ⏩低成本.全要素.高效获取 ⏩数据采集.处理到应用无缝衔接 DJI Terra大疆智图 DJI Terra大疆智图是一款提供自主航线规划.飞行航 ...

  5. 每日一问:说说你对 LeakCanary 的了解

    昨天的问题说到了关于 内存泄漏需要注意的点,在文章最后有说到 LeakCanary 检测内存泄漏.实际上,我相信绝大多数人也知道甚至使用过这个库. 这个系列通常来说如果发现了不错的资源,会选择直接截取 ...

  6. [Gamma]阶段发布说明

    小小易校园微信小程序发布说明 第二版小小易校园小程序发布啦~ 打开微信,点击右上角➕,选择扫一扫,扫描以下二维码即可进入小程序: 版本功能: 上一版功能请参见[Beta阶段]发布说明. 当前版本的更新 ...

  7. 【操作系统之七】Linux常用命令之tail

    一.概念linux tail命令用途是按照要求将指定的文件的最后部分输出到标准设备,一般是终端,就是把某个档案文件的最后几行显示到终端上,如果该档案有更新,tail会自动刷新,确保你看到最新的档案内容 ...

  8. c# .net 使用Confluent.Kafka针对kafka进行生产和消费

    首先说明一点,像Confluent.Kafka这种开源的组件,三天两头的更新.在搜索引擎搜索到的结果往往用不了,浪费时间.建议以后遇到类似的情况直接看官网给的Demo. 因为搜索引擎搜到的文章,作者基 ...

  9. Oracle--存储过程中之循环语句

    一般循环语句有两种: 1)使用for循环实现 declare  cursor cur is    select * from tablename;   aw_row  tablename%rowtyp ...

  10. StringTable

    首先看这样一个面试题 // StringTable [ "a", "b" ,"ab" ] hashtable 结构,不能扩容 public ...