rest framework 之视图
一、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
- 增删:
CreateModelMixin
、DestroyModelMixin
、GenericViewSet
- 复杂逻辑:
GenericViewSet
或APIView
rest framework 之视图的更多相关文章
- Django Rest framework 之 视图
RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...
- Django rest framework (视图类详解)
官网:https://www.django-rest-framework.org/api-guide/viewsets/ 在django rest framework 视图中一共有N个类 第一类:AP ...
- DRF Django REST framework 之 视图组件(四)
引言 在我们有几十上百的视图类,都有get,post等方法,在功能类似时,会导致大量的重复代码出现,显然还有很多可以优化的地方.这也就有了视图组件,它的功能非常强大,能很好的优化接口逻辑. 视图组件 ...
- rest framework之视图组件
一.APIView APIView继承的是和django中CBV模式下的View类.View类中的dispatch方法通过反射对不同的请求方法执行不同的函数.而APIView不仅拥有这个特性,而且重 ...
- Django rest framework(8)---- 视图和渲染器
django rest framework 之视图 序列化器 PagerSerialiser from rest_framework import serializers from api im ...
- Django REST framework 中的视图
1.Request REST framework传入视图的request对象不再是Django默认的Httprequest对象,而是DRF提供的扩展类的Request类的对象 常用属性 request ...
- django的rest framework框架——分页、视图、路由、渲染器
一.rest framework的分页 1.使用rest framework内置类PageNumberPagination实现分类 from django.conf.urls import url f ...
- Django 学习之Rest Framework 视图相关
drf除了在数据序列化部分简写代码以外,还在视图中提供了简写操作.所以在django原有的django.views.View类基础上,drf封装了多个子类出来提供给我们使用. Django REST ...
- iOS 系统架构 && 常用 framework
整理自互联网,感谢原文作者! 1.iOS基于UNIX系统,因此从系统的稳定性上来说它要比其他操作系统的产品好很多 2.iOS的系统架构分为四层,由上到下一次为:可触摸层(Cocoa Touch lay ...
随机推荐
- 使用emplace操作
C++ 11新标准中引入了三个新成员——emplace_front.emplace和emplace_back,这些操作构造而不是拷贝元素.这些操作分别对应push_front.insert和push_ ...
- 网络协议 17 - HTTPDNS
全球统一的 DNS 是很权威,但是我们都知道“适合自己的,才是最好的”.很多时候,标准统一化的 DNS 并不能满足我们定制的需求,这个时候就需要 HTTPDNS 了. 上一节我们知道了 DNS ...
- 微信网页分享使用了jssdk,分享图还是不显示的几个坑
坑爹的微信分享,设置图片链接必须要满足如下条件: 1. 微信分享图链接必须是绝对路径,写相对地址不行. 比如图片地址写成 './assets/images/share.jpg' 不行!!! 必须写成 ...
- V8 引擎如何进行垃圾内存的回收?
JS 语言不像 C/C++, 让程序员自己去开辟或者释放内存,而是类似Java,采用自己的一套垃圾回收算法进行自动的内存管理.作为一名资深的前端工程师,对于JS内存回收的机制是需要非常清楚, 以便于在 ...
- 安装-consul服务发现集群
centos 7.4.x consul 1.2.2 list: 172.16.16.103 172.16.16.112 172.16.16.115 下载: #cd /usr/local/ #wget ...
- Gamma阶段发布说明
访问我们 公课网 Gamma新增功能和缺陷修复 Gamma新增功能 增加找回密码功能~妈妈再也不用担心我的密码忘掉了. 增加管理员功能,有权删除评论并通知用户. 增加信箱功能,评论被管理员删除后会得到 ...
- linux的arp表满导致同网段无法ping通
由于历史原因,有一个网段子网设置非常大10.0.0.0/21,8个C地址段为一个子网. linux内核默认arp表大小为1024,导致一台监控机器arp表溢出,同时导致日志输出速率超出限制,无法输出日 ...
- docker compose 编排
Compose是Docker的服务编排工具,主要用来构建基于Docker的复杂应用,Compose 通过一个配置文件来管理多个Docker容器,非常适合组合使用多个容器进行开发的场景. 说明:Comp ...
- dockerfile 命令
FROM 功能为指定基础镜像,并且必须是第一条指令. 如果不以任何镜像为基础,那么写法为:FROM scratch. 同时意味着接下来所写的指令将作为镜像的第一层开始 语法: FROM <ima ...
- Codeforces 878 E. Numbers on the blackboard
Codeforces 878 E. Numbers on the blackboard 解题思路 有一种最优策略是每次选择最后面一个大于等于 \(0\) 的元素进行合并,这样做完以后相当于给这个元素乘 ...