Django Rest framework基础使用之View:APIView, mixins, generic, viewsets
先看一张图,对DRF的各个APIView,Mixin,Viewset等有个基本印象:

具体使用方法:
1、APIView:
DRF 的API视图 有两种实现方式:
一种是基于函数的:@api_view
一种是基于类的:APIView,APIView是Restframework提供的所有视图的基类,继承自Django的View父类
1)@api_view
使用@api_view装饰器,使得我们此处的Request不在是Django标准的HttpRequest,而是restframework的Request。
默认情况下,只有GET请求会被接收,它也允许我们自己配置函数允许接收的请求类型
@api_view():默认只接收GET请求
@api_view(http_method_names=['GET']):指明接收的请求类型
@api_view(['GET', 'POST']):接收get post请求
@api_view(['GET','POST'])
def Snippet_list(request):
if request.method=="GET":
pass
elif request.method == "POST":
pass
2)APIView
APIView是基于类的装饰器,显然,类视图更符合面向对象的原则,它支持GET POST PUT DELETE等请求类型,且各种类型的请求之间,有了更好的分离
在进行dispatch分发之前,会对请求进行身份认证,权限检查,流量控制。
支持定义的属性:
authentication_classes=():列表或元组,身份认证类
permission_classes=():列表或元组,权限检查类
throttle_classes=():列表或元组,流量控制类
class Snippet_list(APIView):
def dispatch(self, request, *args, **kwargs):
# 请求到来之后,都需要执行dispatch方法,dispatch根据请求方式的不同,分别触发对应的get post, put等方法
return super().dispatch(request, *args, **kwargs)
def get(self, request, pk, format=None):
snippet = Snippets.objects.get(pk=pk)
serializer = SnippetSerializer(snippet, many=True)
return Response(serialzer.data)
def post(self, request):
serializer = SnippetSerializer(data = request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
snippet = Snippets.object.get(pk=pk)
snippet.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
配置url:
urlpatterns = [
url(r"^snippets/(?P<pk>[0-9]+)$", Snippet_list.as_view()),
]
2、mixins
使用基于类的视图的一个最大的好处就是我们可以灵活的选择各种View,使我们的开发更加的简洁
mixins里面对应了ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
这些Mixin方法,对我们上面APIView中重写的GET POST PUT DELETE进行了封装,使得我们的代码更加简洁

下面是使用mixin的例子:
GenericAPIView继承了APIView,通过GenericViewSet来构建我们的视图,然后组合ListModelMixin和CreateModelMixin来实现我们上面的代码功能
基类提供了核心的功能,ListModelMixin和CreateModelMixin提供了.list()和.create()函数,下面我们将get和post与.list和.create绑定起来
class snippet_list(mixins.ListModelMixin, generic.GenericAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
3、使用generic
我们上面使用mixin的代码,已经非常简洁了,但是restframework给我们提供了一组混合的generic视图,可以使我们的代码 大大简化
GenericAPIView:继承自APIView,增加了对列表视图或者详情视图可能用到的通用支持方法。通常使用时,可搭配一个或者多个Mixin扩展类
支持定义的属性:
列表视图与详情视图通用:queryset(视图的查询集), serializer_class(视图使用的序列化器)
列表视图专用:pagination_classes(分页控制类),filter_backends(过滤控制)
详情页视图专用:lookup_field(查询单一数据库对象时使用的条件字段,默认为pk)
提供的方法:
通用:
1)get_queryset(self):返回视图使用的查询集,是获取数据的基础,默认返回queryset,可以重写:
def get_queryset(self):
user = self.request.user
return user.accounts.all()
2)get_serializer_class(self):返回序列化器,默认返回serializer_class,可以重写,如:
def get_serializer_class(self):
if self.request.user.is_staff:
return AllAccountSerializer
return BasicAccountSerializer
3)get_serializer(self, *args, **kwargs):返回序列化器对象
详情视图使用:
get_object(self):返回详情视图所需的模型类数据对象,默认使用lookup_field参数来过滤queryset
该方法默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问
class SnippetDetail(GenericAPIView):
queryset = Snippets.objects.all()
seriazlier_class = SnippetSerializer
def get(self, request, pk):
snippet = self.get_object()
serializer = self.get_serializer(snippet)
return Response(serialzier.data)
url:url(r"^snippet/?P<pk>[0-9]+/$", SnippetDetail.as_view())
五个扩展类:generics.ListAPIView, generics.CreateAPIView, generic.RetrieveAPIView, generic.UpdateAPIView, generic.DestroyAPIView,它们会继承GenericAPIView和mixin对应的视图

上面可以看到generics.ListAPIView里面做的事情,它替我们继承了mixins.ListModelMixin和GenericAPIView,还重写了get方法,所以我们直接继承generic.ListAPIView,代码就会更简洁,
只需要设置一下queryset和serializer_class即可,如下:
class snippet_list(generics.ListAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
4、视图集ViewSet
使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中。
list():提供一组数据
retrieve():提供单个数据
create():创建数据
destroy():删除数据
update():修改数据
ViewSet主要是和路由搭配使用,将我们通常使用的get, post等和方法和ViewSet实现的action如list(), create()等对应上。
action属性:
在视图集中,我们可以通过action对象属性来确定当前请求视图集时的action动作是哪个
def get_serializer_class(self):
if self.action == "create":
return SnippetCreateSerializer
else:
return SnippetListSerializer
url配置:
urlpatterns = [
url(r"^snippet/$", SnippetViewSet.as_view({"get":"list", "post":"create"})),
url(r"^snippet/?P<pk>[0-9]+/$", SnippetViewSet.as_view({"get":"retrive"})),
]
上面url配置,是我们手动的将请求方式和action动作对应起来,其实restframework也已经帮我对应好了,它是通过Router模块来完成的,我们只需要使用router将对应的视图注册即可。
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r"snippet", SnippetViewSet)
urlpatterns = [
url(r"^", include(router.urls))
]
5、Django restframework 过滤器
如过滤文章阅读量小于100的:
class ArticleViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
def get_queryset(self):
read_nums = self.query_params.get("readNums", 0)
if read_nums:
return Article.objects.filter(read_nums__lt=int(read_nums))
return Article.objects.all()
上面这种方式,如果过滤字段少的话,可以方便使用,但是如果过滤字段多,那代码量就会很繁复了。如果还想要用简洁的代码实现大量的过滤逻辑,就需要用到其他方法,如django-filter
pip install django-filter,并将django-filter加入到INSTALLED_APPS中。
如:
from django_filters.rest_framework import DjangoFilterBackend
class ArticleViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerialzier
filter_backends = (DjangoFilterBackend, )
filter_fields = ("name", "title")
这种写法相对于上面第一种写法就简单很多了,但是如果我们想要查询阅读数量大于10,小于100的文章要怎么办呢?所以这种写法还是有他的局限性,要实现这种情况的过滤,需要我们自定义过滤器:
新建filters.py
import django_filters
class ArticleFilter(django_filters.rest_framework.FilterSet):
title= django_filters.CharFilter(lookup_expr='icontains')
readNums = django_filters.NumberFilter(lookup_expr="gte")
class Meta:
model = Article
fields = ["min_readers","readNums", "clickNums"]
说明:
上面:model:Article---指出该类是为Article 这个model定义的过滤类
lookup_expr------指出过滤条件,是包含,还是大于或是其他,后面会想起说明
fields----------------指定了支持过滤的字段,如果fields中指定了字段,但是没有指定过滤方法,则表示精确查询
view中使用:
class SnippetViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
filter_backends = (DjangoFilterBackends, )
filter_class = ArticleFilter
多表过滤:
class Book(model.Model):
name = model.CharField(max_length = 50)
class Author(model.Model):
name = model.CharField(max_length=20)
book = model.ForeignKey(Book)
例如上面的作者和书是一对多的关系,一个人可以写多本书。那么我们想要通过书本的名字去查询它的作者,要怎么做呢?
class AuthorFilter(django_filters.rest_framework.FilterSet):
book__name = django_filters.CharFilter(lookup_expr='icontains')
class Meta:
model = Author
fields = ["book__name"]
在View中使用:
按照上面的单表查询的View写法也是可以的,这里我们通过另一种重写list的方式来完成,旨在说明自定义分页的写法。
class AuthorViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
queryset = Author.objects.all()
serializer = AuthorSerializer
def list(self, request, *args, **kwargs):
object = AuthorFilter(request.query_params, queryset=self.queryset)
# 过滤后查询出的数据
filterRecords = object.qs.count()
# 前端传过来的参数:当前第几页
curP = int(request.query_params.get("p", 0))
# 前端传过来的参数:每页有几条数据
size = int(request.query_params.get("s", 0))
if curP and size:
start = (curP-1)*size
length = size
else:
start = 0
length = filterRecords
# 通过调用过滤器的返回值的qs来处理自定义分页,有兴趣的话可以去django.db.model.query.py中去看看
object = object.qs[start:(start+length)]
serializer = self.get_serializer(object, many = True)
return Response(serializer.data)
Django Rest framework基础使用之View:APIView, mixins, generic, viewsets的更多相关文章
- Django rest framework 基础
01: Django rest framework 基础 1.1 什么是RESTful 1. REST与技术无关,代表的是一种软件架构风格(REST是Representational Stat ...
- 01: Django rest framework 基础
1.1 RESTful API设计规范 参考地址: http://www.cnblogs.com/wupeiqi/articles/7805382.html 1.API与用户的通信协议,总是使用H ...
- Django REST framework基础:视图和路由
DRF中的Request 在Django REST Framework中内置的Request类扩展了Django中的Request类,实现了很多方便的功能--如请求数据解析和认证等. 比如,区别于Dj ...
- Django Rest framework基础使用之 serializer
rest-framework文档地址:http://www.django-rest-framework.org/ Django Rest framework是一个非常强大且灵活的工具包,用于构建web ...
- Django REST framework基础:认证、权限、限制
认证.权限和限制 身份验证是将传入请求与一组标识凭据(例如请求来自的用户或其签名的令牌)相关联的机制.然后 权限 和 限制 组件决定是否拒绝这个请求. 简单来说就是: 认证确定了你是谁 权限确定你能不 ...
- Django REST framework基础:分页
DRF分页组件 为什么要使用分页 我们数据表中可能会有成千上万条数据,当我们访问某张表的所有数据时,我们不太可能需要一次把所有的数据都展示出来,因为数据量很大,对服务端的内存压力比较大还有就是网络传输 ...
- Django REST framework基础:版本、认证、权限、限制
1 认证.权限和限制 2 认证 2.1 自定义Token认证 2.1.1 表 2.1.2 定义一个登录视图: 2.1.3 定义一个认证类 2.1.4 视图级别认证 2.1.5 全局级别 ...
- Django Rest framework基础使用之Request/Response
1.Request restframework提供了一个Request对象(rest_framework.request.Request) Request对象继承了Django默认的HttpReque ...
- Django REST framework基础:解析器和渲染器
解析器 解析器的作用 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己可以处理的数据.本质就是对请求体中的数据进行解析. 在了解解析器之前,我们要先知道Accept以及ContentTy ...
随机推荐
- shell编程-test命令(七)
test命令常用作检查某些条件是否成立. 数值测试 -eq:检测两个数是否相等,相等返回true -ne:检测两个数是否相等,不相等返回true -gt:检测左边的数是否大于右边,是则返回true - ...
- javaweb分页查询实现
Javaweb分页技术实现 分页技术就是通过SQL语句(如下)来获取数据,具体实现看下面代码 //分页查询语句 select * from 表名 where limit page , count; 和 ...
- window.onunload中使用HTTP请求
在页面关闭时触发window.onunload 在onunload中要使用http请求,需要使用同步请求: 如: $.ajax({ url: url, async: false }); iframe页 ...
- Linux中FTP的一点理解
FTP(File Transfer Protocol)是一个非常古老并且应用十分广泛的文件传输协议,FTP协议是现今使用最为广泛的网络文件共享协议之一,我们现在也一直有在用着FTP协议来进行各种文件的 ...
- oracle USING 用法
提问 using(xx)中可以接多个列吗? using(xx)中的列可以接表名或别名吗? 在使用using的语句中,select * 可以使用吗? 如果表有别名t,select t.* from ta ...
- 约瑟夫环简介,问题以及java实现
问题:一群猴子排成一圈,按1,2,--.,n依次编号.然后从第一只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,再把它踢出去-------.,如此不停的进行下去,直到最后只剩下一只猴 ...
- Linux 小知识翻译 - 「UTC 和 JST」
这周解释下「UTC 和 JST」. 地球上的国家之间是存在时差的.然而互联网是遍布全球的网络,跨国境的数据传输是很频繁的.因此,互联网上的服务器就需要一个共通的时间. 实际上,互联网上的服务器,大部分 ...
- #000 Python 入门第一题通过扩展,学到了更多的知识
#1写在前面的话 我觉得这样学习或许能够在学习的过程中事半功倍 第一道简单的python编写代码输出10行带标号的“Hello,world.”,具体效果参阅输入输出示例 1:Hello,world. ...
- MySQL高级知识(六)——索引优化
前言:索引优化的目的主要是让索引不失效,本篇通过相关案例对索引优化进行讲解. 0.准备 创建经典的tb_emp表. DROP TABLE IF EXISTS `tb_emp`; CREATE TABL ...
- SQLite 知识摘要 --- 线程模式、事务模式
本篇主要从SQLite事务执行的原理中寻找如何更高效地使用它. 本篇预备知识 我们先来了解下SQLite执行事务的基本流程,状态变化过程,再分析怎么使用才更优.SQLite定义的锁的状态有如下几种: ...