官方文档:http://www.django-rest-framework.org/

drf为我们提供强大的通用view的功能,本博客对这些view进行简要的总结分析。

首先,我们看一下主要的几种view以及他们之间的关系。



这其中,还涉及了mixins,主要也分为5类:

下面我们以课程(course)作为一个例子,对view进行一个总结。

1. django View

首先,我们使用django自带的view,获取一个课程的列表:

# drf是通过json的格式进行数据交互的,所以这里也返回json数据
import json
from django.views.generic.base import View
from django.core import serializers
from django.http import HttpResponse,JsonResponse
from .models import Course class CourseListView(View):
def get(self, request):
"""
通过django的view实现课程列表页
"""
courses = Course.objects.all()[:10]
json_data = serializers.serialize('json', courses)
json_data = json.loads(json_data)
return JsonResponse(json_data, safe=False)

2. APIView

接下来,我们用APIView来实现

from rest_framework.views import APIView
from rest_framework.response import Response
# 这个serializers是在其他文件自定义的,这里对这个不进行过多介绍
from .serializers import CourseSerializer class CourseListView(APIView):
def get(self, request, format=None):
"""
通过APIView实现课程列表页
"""
courses = Course.objects.all()
serializer = CourseSerializer(courses, many=True)
return Response(serializer.data)

在APIView这个例子中,调用了drf本身的serializer以及Response方法。

  APIView对django本身的View进行封装,从上述的代码,这样分析,两者的差别看起来不是很大,但实际中APIView做了很多东西,它定义了很多属性与方法,举几个例子

# 这三个是常用的属性
authentication_classes : 用户登录认证方式,session或者token等等
permission_classes : 权限设置,是否需要登录等
throttle_classes : 限速设置,对用户进行一定的访问次数限制等等。

到这里,可能还不能体现drf通过view的强大之处,那么接下来的GenericAPIView就展示了它强大的功能。

3. GenericAPIView

from rest_framework import mixins
from rest_framework import generics
class CourseListView(mixins.ListModelMixin, generics.GenericAPIView):
"""
课程列表页
"""
queryset = Course.objects.all()
serialize_class = CourseSerializer
def get(self, request, *args, **kwargs):
# list方法是存在于mixins中的,同理,create等等也是
# GenericAPIView没有这些方法!
return self.list(request, *args, **kwargs)

在这个例子中,继承了mixins中的ListModelMixin,在get( )方法中,调用了它的list( )方法,list方法会返回queryset的json数据。这里对mixins不进行过多的介绍。

GenericAPIView对APIView再次封装,实现了强大功能:

  • 加入queryset属性,可以直接设置这个属性,不必再将实例化的courses,再次传给seriliazer,系统会自动检测到。除此之外,可以重载get_queryset(),这样就不必设置’queryset=*’,这样就变得更加灵活,可以进行完全的自定义。
  • 加入serializer_class属性与实现get_serializer_class()方法。两者的存在一个即可,通过这个,在返回时,不必去指定某个serilizer
  • 设置过滤器模板:filter_backends
  • 设置分页模板:pagination_class
  • 加入 lookup_field=”pk”,以及实现了get_object方法: 这个用得场景不多,但十分重要。它们两者的关系同1,要么设置属性,要么重载方法。它们的功能在于获取某一个实例时,指定传进来的后缀是什么。

举个例子,获取具体的某个课程,假设传进来的ulr为:http://127.0.0.1:8000/course/1/,系统会默认这个1指的是course的id。那么,现在面临一个问题,假设我定义了一个用户收藏的model,我想要知道我id为1的课程是否收藏了,我传进来的url为:http://127.0.0.1:8000/userfav/1/,系统会默认获取userfav的id=1的实例,这个逻辑明显是错的,我们需要获取course的id=1的收藏记录,所以我们就需要用到这个属性或者重载这个方法 lookup_field=”course_id”.

在generics除了GenericAPIView还包括了其他几个View: CreateAPIView、ListAPIView、RetrieveAPIView、ListCreateAPIView···等等,其实他们都只是继承了相应一个或多个mixins和GenericAPIView,这样,有什么好处?我们看一下同样一个例子的代码:

class CourseListView(ListAPIView):
"""
课程列表页
"""
queryset = Course.objects.all()
serialize_class = CourseSerializer

这样,就完成了和刚刚一模一样的功能!

4.GenericViewSet

  • GenericAPIView的不足之处

    既然GenericAPIView以及它相关的View已经完成了许许多多的功能,那么还要ViewSet干嘛!

首先,我们思考一个问题,同样上面的例子,我们在功能上,要获取课程的列表,也要获取某个课程的具体信息。那么怎么实现,按照GenericAPIView,我们可以这样实现:

class CourseView(ListAPIView,RetrieveAPIView):
# 只需要在上面的基础上,再继承RetrieveAPIView就ok了。
queryset = Course.objects.all()
serialize_class = CourseSerializer

但这样实现有一个问题,关于serialize_class,显然,当获取课程列表时,只需要传回去所有课程的简要信息,如课程名字,老师,封面等等,但当获取课程的具体信息,我们还要将他们的章节以及相关下载资料(很明显,章节是另外一个model,有一个外键指向course),这些信息会很多,在获取课程列表,将这些传回去显然是不理智的。那么,还需要再定义一个CourseDetailSerializer,在get /courses/的时候,使用CourseSerializer,在get /courses/id/的时候,使用CourseDetailSerializer。

  那么,问题来了,我们怎么获取到是哪个action方法?这个时候,viewset就出场了!

  • viewset的功能

      GenericViewSet继承了GenericAPIView,依然有get_queryset,get_serialize_class相关属性与方法,GenericViewSet重写了as_view方法,可以获取到HTTP的请求方法。

    解决刚刚的问题
from rest_framework import viewsets
import...
class CourseViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
queryset = Course.objects.all() def get_serializer_class(self):
# 重写get_serializer_class方法
if self.action == 'list':
return CourseSerializer
return CourseDetailSerializer
  • http请求方法与mixins的方法进行绑定

      但GenericViewSet本身依然不存在list, create方法,需要我们与mixins一起混合使用,那么新问题来了?我们依然需要自己写get、post方法,然后再return list或者create等方法吗?当然不!重写as_view的方法为我们提供了绑定的功能,我们在设置url的时候:
# 进行绑定
courses = CourseViewSet.as_view({
'get': 'list',
'post': 'create'
})
urlpatterns = [
...
# 常规加入url匹配项
url(r'courses/', CourseViewSet.as_view(), name='courses'),]

这样,我们就将http请求方法与mixins方法进行了关联。那么还有更简洁的方法吗?很明显,当然有,这个时候,route就登场了!

  • route方法注册与绑定

    from rest_framework.routers import DefaultRouter

    router = DefaultRouter() # 只需要实现一次

    router.register(r'courses', CourseViewSet, base_name='courses')

    urlpatterns = [

    ...

    只需要

    url(r'^', include(router.urls)),]

    route中使用的一定要是ViewSet,用router.register的方法注册url不仅可以很好的管理url,不会导致url过多而混乱,而且还能实现http方法与mixins中的相关方法进行连接。

      在viewset中,还提供了两个以及与mixins绑定好的ViewSet,当然,这两个ViewSet完全可以自己实现:

class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
mixins.ListModelMixin,
GenericViewSet):
# 满足只有GET方法请求的情景
pass class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
# 满足所有请求都有的情景
pass

到这里,ViewSet的强大功能就介绍完了,强烈建议在做drf的时候,使用ViewSet与mixins方法结合进行开发,为我这种小白开发者提供了很强大完整的功能!

django rest framework通用view的更多相关文章

  1. Django REST framework+Vue 打造生鲜超市(四)

    五.商品列表页 5.1.django的view实现商品列表页 (1)goods/view_base.py 在goods文件夹下面新建view_base.py,为了区分django和django res ...

  2. 用Django Rest Framework和AngularJS开始你的项目

    Reference: http://blog.csdn.net/seele52/article/details/14105445 译序:虽然本文号称是"hello world式的教程&quo ...

  3. Django REST framework+Vue 打造生鲜超市(一)

    一.项目介绍 1.1.掌握的技术 Vue + Django Rest Framework 前后端分离技术 彻底玩转restful api 开发流程 Django Rest Framework 的功能实 ...

  4. python 全栈开发,Day96(Django REST framework 视图,django logging配置,django-debug-toolbar使用指南)

    昨日内容回顾 1. Serializer(序列化) 1. ORM对应的query_set和ORM对象转换成JSON格式的数据 1. 在序列化类中定义自定义的字段:SerializerMethodFie ...

  5. python 全栈开发,Day94(Promise,箭头函数,Django REST framework,生成json数据三种方式,serializers,Postman使用,外部python脚本调用django)

    昨日内容回顾 1. 内容回顾 1. VueX VueX分三部分 1. state 2. mutations 3. actions 存放数据 修改数据的唯一方式 异步操作 修改state中数据的步骤: ...

  6. django rest framework restful 规范

    内容回顾: . django请求生命周期 -> 执行遵循wsgi协议的模块(socket服务端) -> 中间件(路由匹配) -> 视图函数(业务处理:ORM.模板渲染) -> ...

  7. 关于Rest Framework中View、APIView与GenericAPIView的对比分析

    关于Rest Framework中View.APIView与GenericAPIView的对比分析  https://blog.csdn.net/odyssues_lee/article/detail ...

  8. 1- vue django restful framework 打造生鲜超市

    Vue+Django REST framework实战 使用Python3.6与Django2.0.2(Django-rest-framework)以及前端vue开发的前后端分离的商城网站 项目支持支 ...

  9. Django Rest Framework 教程及API向导

    Django Rest Framework 教程及API向导. 一.请求(Request)REST_FRAMEWORK 中的 Request 扩展了标准的HttpRequest,为 REST_FRAM ...

随机推荐

  1. Pandas字符串操作及实例应用

    字符串操作 字符串对象方法 val = 'a,b, guido' val.split(',') ['a', 'b', ' guido'] pieces = [x.strip() for x in va ...

  2. json and pickle 序列化

    前言 文件只能存储字符串.二进制,若把内存的数据对象存到硬盘   从硬盘里读取数据,里面不止是字符串的类型,因此用到了json and pickle 序列化 json序列化 作用:用于不同语言进行的数 ...

  3. C# dns.gethostentry()获取失败,提示不存在主机

    传入参数domain有误. 如果是域名,可以解析.如果是局域ip可以解析. 如果是外网,解析不成功. 解决方法: 判断传入参数是域名还是ip,如果是域名,则使用dns.gethostentry(dom ...

  4. Dubbo helloword

    首先,开始编写服务提供者的api接口, SampleService  接口 package bhz.dubbo.sample.provider; import java.util.List; publ ...

  5. 281. Zigzag Iterator z字型遍历

    [抄题]: Given two 1d vectors, implement an iterator to return their elements alternately. Example: Inp ...

  6. Java最小化镜像制作

    下载Oracle官网的JRE包,最终下载的包如下: jre-8u181-linux-x64.tar.gz 解压JRE包并删除不必要的文件 #解压 tar xf jre-8u181-linux-x64. ...

  7. PyCharm选择性忽略PEP8代码风格警告信息

    用了几天的PyCharm,发现确实在编写Python代码上非常好用,但有一点体验不太好,就是代码编写时要按照PEP8代码风格编写,不然会有波浪线的警告信息.解决方法如下: 方法一: 将鼠标移到提示的地 ...

  8. pyhton 核心编程 正则表达式习题

    方案一 import re #1. 识别下列字符串:“bat,” “bit,” “but,” “hat,” “hit,” 或 “hut” import re def test1(self): bt = ...

  9. UML类图中箭头和线条的含义和用法

    UML类图中箭头和线条的含义和用法 在学习UML过程中,你经常会遇到UML类图关系,这里就向大家介绍一下UML箭头.线条代表的意义,相信通过本文的介绍你对UML中箭头.线条的意义有更明确的认识. AD ...

  10. 学习Acegi应用到实际项目中(2)

    Acegi应用到实际项目中(1)是基于BasicProcessingFilter的基本认证,这篇改用AuthenticationProcessingFilter基于表单的认证方式. 1.authent ...