DRF的视图

APIView

Django中写CBV的时候继承的是View,rest_framework继承的是APIView,

urlpatterns = [
url(r'^book$', BookView.as_view()),
# url(r'^book/(?P<id>\d+)', BookEditView.as_view()),
url(r'^book$', BookModelView.as_view({"get": "list", "post": "create"})),
# url(r'^book/(?P<pk>\d+)', BookModelView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
]

View和APIView调用的都as_view()方法,我们知道APIView继承了View,并且重写了as_view()方法,并执行了View中的as_view()方法,最后把view返回了,用csrf_exempt()方法包裹后去掉了csrf的认证。看下图:

APIView还执行了dispatch方法,新的request是Request类的实例化对象,看下图:

我们看看initialize_request中的代码实现了什么功能:

点击Request可以看到Request类把原来的request赋值给了self._request,也就是说以后_request是我们旧的request,看下图:

继承APIVIew之后的请求来的数据,看下图:

当用了rest_framework框架后,我们的request是重新封装的Request类

request.query_params存放的是我们get请求的参数

request.data存放的是我们所有的数据,包括post请求的以及put,patch请求

相比原来的Django的request,我们现在的request更加精简,清晰了

由于我们写的视图可能对多个表进行增删改查,就导致我们的视图特别多重复的代码

所以我们需要封装一下。

第一次封装

因为代码中除了序列化器不同以及获取的queryset对象不同,其他的都类似。所有我们它相同的代码封装出来,提高代码的复用性。

  APIView视图

class BookView(APIView):

    def get(self, request):
query_set = Book.objects.all()
book_ser = BookSerializer(query_set, many=True)
return Response(book_ser.data) def post(self, request):
query_set = request.data
book_ser = BookSerializer(data=query_set)
if book_ser.is_valid():
book_ser.save()
return Response(book_ser.validated_data)
else:
return Response(book_ser.errors) class BookEditView(APIView): def get(self, request, id):
query_set = Book.objects.filter(id=id).first()
book_ser = BookSerializer(query_set)
return Response(book_ser.data) def patch(self, request, id):
query_set = Book.objects.filter(id=id).first()
book_ser = BookSerializer(query_set, data=request.data, partial=True)
if book_ser.is_valid():
book_ser.save()
return Response(book_ser.validated_data)
else:
return Response(book_ser.errors) def delete(self, request, id):
query_set = Book.objects.filter(id=id).first()
if query_set:
query_set.delete()
return Response("")
else:
return Response("删除的书籍不存在")

  第一次封装

from django.shortcuts import render
from rest_framework.views import APIView
from djangoDemo.models import Book
from .serializers import BookSerializer
from rest_framework.response import Response # queryset不同
# 序列化器不同
# def get():
# def post(): class GenericAPIView(APIView):
queryset = None
serializer_class = None def get_queryset(self):
# 放到缓存中再拿出来时就需要我们用all()来获取,这是Django机制导致的
return self.queryset.all() def get_serializer(self, *args, **kwargs):
return self.serializer_class(*args, **kwargs) class ListModelMixin(object):
def list(self, request):
# 调用外部的get方法
# 执行父类的方法
queryset = self.get_queryset()
# 实例化序列化器
ser_obj = self.get_serializer(queryset, many=True)
return Response(ser_obj.data) class CreateModelMixin(object):
def create(self, request):
ser_obj = self.get_serializer(data=request.data)
if ser_obj.is_valid():
ser_obj.save()
# 校验过的数据存放在validated_data中
return Response(ser_obj.validated_data)
return Response(ser_obj.errors) class RetrieveModelMixin(object):
def retrieve(self, request, id):
book_obj = self.get_queryset().filter(id=id).first()
ser_obj = BookSerializer(book_obj)
return Response(ser_obj.data) class UpdateModelMixin(object):
def update(self, request, id):
book_obj = self.get_queryset().filter(id=id).first()
ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True)
if ser_obj.is_valid():
ser_obj.save()
# 去反序列化以后的数据中去找到并返回
return Response(ser_obj.validated_data)
return Response(ser_obj.errors) class DestroyModelMixin(object):
def destroy(self, request, id):
book_obj = self.get_queryset().filter(id=id).first()
if not book_obj:
return Response('删除的数据不存在')
book_obj.delete()
return Response('') class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer def get(self, request):
# 封装ListModelMixin类以后的执行过程
return self.list(request) # 只封装GenericAPIView类的执行过程
# # 调用外部的get方法
# # 执行父类的方法
# queryset = self.get_queryset()
# # 实例化序列化器
# ser_obj = self.get_serializer(queryset, many=True)
# return Response(ser_obj.data) # 没封装之前
# book_queryset = Book.objects.all()
# 用序列化器进行序列化
# ser_obj = BookSerializer(book_queryset, many=True)
# 通过点data来获取数据
# return Response(ser_obj.data) # 没封装前的post执行过程
# def post(self, request):
# # 获取从前端传递过来的值
# book_obj = request.data
# # data=book_obj就是反序列化时的对象数据
# ser_obj = BookSerializer(data=book_obj)
# if ser_obj.is_valid():
# ser_obj.save()
# # 反序列化以后的数据放在validated_data中
# return Response(ser_obj.validated_data)
# # 如果校验不成功则返回错误信息
# return Response(ser_obj.errors) # 继承CreateModelMixin类后的post执行过程
def post(self, request):
return self.create(request) class BookEditView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer def get(self, request, id):
# book_obj = Book.objects.filter(id=id).first()
# ser_obj = BookSerializer(book_obj)
# return Response(ser_obj.data)
return self.retrieve(request, id) def put(self, request, id):
# book_obj = Book.objects.filter(id=id).first()
# ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True)
# if ser_obj.is_valid():
# ser_obj.save()
# # 去反序列化以后的数据中去找到并返回
# return Response(ser_obj.validated_data)
# return Response(ser_obj.errors)
return self.update(request, id) def delete(self, request, id):
# book_obj = Book.objects.filter(id=id).first()
# if not book_obj:
# return Response('删除的数据不存在')
# book_obj.delete()
# return Response('')
return self.destroy(request, id)

第二次封装

# 我们把继承的类封装了一下
class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
pass class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
pass class BookView(ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer def get(self, request):
# 封装ListModelMixin类以后的执行过程
return self.list(request) # 继承CreateModelMixin类后的post执行过程
def post(self, request):
return self.create(request) class BookEditView(RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer def get(self, request, id):
return self.retrieve(request, id) def put(self, request, id):
return self.update(request, id) def delete(self, request, id):
return self.destroy(request, id)

第三次封装

我们可不可以把这两个视图合并成一个视图呢~~~框架给我们提供了一个路由传参的方法~~

actions这个默认参数其实就是我们路由可以进行传参了~~~

下面这个循环~可以看出~我们要传的参数是一个字段~key应该是我们的请求方式,value应该对应我们处理的方法~

这样我们每个视图就不用在写函数了~因为已经和内部实现的函数相对应了~

  路由urls.py

from django.conf.urls import url, include
from .views import BookView, BookEditView, BookModelView
# 帮助我们生成带参数的路由
from rest_framework.routers import DefaultRouter
# 实例化DefaultRouter对象
router = DefaultRouter()
# 注册我们的路由以及视图
router.register(r'^book', BookModelView) urlpatterns = [
url(r'^book$', BookView.as_view()),
# url(r'^book/(?P<id>\d+)', BookEditView.as_view()),
url(r'^book$', BookModelView.as_view({"get": "list", "post": "create"})),
# url(r'^book/(?P<pk>\d+)', BookModelView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})), ] urlpatterns += router.urls

  第三次封装

ViewSetMixin  重写了as_view()方法

from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from djangoDemo.models import Book
from .serializers import BookSerializer
from rest_framework.viewsets import ViewSetMixin from rest_framework import views # APIView
from rest_framework import viewsets
from rest_framework import generics
from rest_framework import mixins # 自定义了一个类,
class ModelViewSet(ViewSetMixin, ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin):
pass # 然后继承它
class BookModelView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer

  由于第三次封装所以路由发生了改变:

from django.conf.urls import url, include
from .views import BookView, BookEditView, BookModelView urlpatterns = [
url(r'^book/$', BookModelView.as_view({"get": "list", "post": "create"})),
url(r'^book/(?P<pk>\d+)/',
BookModelView.as_view({"get": "list", "post": "create", "put": "update", "delete": "destroy"})),
]

  注意一点~~用框架封装的视图~我们url上的那个关键字参数要用pk~~系统默认的~~

看看我们的继承顺序

DRF的路由

路由

from django.conf.urls import url, include
from .views import BookView, BookEditView, BookModelView # 帮我们生成带参数的路由(我们原本是不能传递参数的在路由中)
from rest_framework.routers import DefaultRouter # 实例化DefaultRouter对象
router = DefaultRouter() # 注册我们的路由以及视图
router.register(r'book', BookModelView) urlpatterns = [
# url(r'^book/$', BookView.as_view()),
# url(r'^book/(?P<pk>\d+)/', BookEditView.as_view()),
# url(r'^book/$', BookModelView.as_view({"get": "list", "post": "create"})),
# url(r'^book/(?P<pk>\d+)/',
# BookModelView.as_view({"get": "list", "post": "create", "put": "update", "delete": "destroy"})),
] urlpatterns += router.urls

  需要自定制的时候还是需要我们自己用APIView写~~当不需要那么多路由的时候~也不要用这种路由注册~~

  

DRF的视图和路由的更多相关文章

  1. DRF 的视图,路由和渲染器

    DRF 的视图,路由和渲染器 1 视图 简单的增删改查 : ModelViewSet; 复杂的操作使用APIView 和 GenericViewSet APIView(View) class Home ...

  2. restfull规范、DRF视图和路由

    一.restfull规范的简单介绍 1.介绍 REST:表述性状态转移,是一种web交互方案 资源:在web中只要有被引用的必要都是资源 URI: URI 统一资源标识符 URL 统一资源定位符 统一 ...

  3. DRF 视图和路由

    Django Rest Feamework 视图和路由 DRF的视图 APIView 我们django中写CBV的时候继承的是View,rest_framework继承的是APIView,那么他们两个 ...

  4. DRF 视图组件,路由组件

    视图组件  -- 第一次封装   -- GenericAPIView(APIView):    queryset = None    serializer_class = None    def ge ...

  5. Django REST framework基础:视图和路由

    DRF中的Request 在Django REST Framework中内置的Request类扩展了Django中的Request类,实现了很多方便的功能--如请求数据解析和认证等. 比如,区别于Dj ...

  6. Django Rest Framework 视图和路由

    Django Rest Framework 视图和路由   DRF的视图 APIView 我们django中写CBV的时候继承的是View,rest_framework继承的是APIView,那么他们 ...

  7. DRF的视图

    DRF的视图 APIView 我们django中写CBV的时候继承的是View,rest_framework继承的是APIView,那么他们两个有什么不同呢~~~ urlpatterns = [    ...

  8. DRF之视图和router

    1. 视图 Django REST framwork 提供的视图的主要作用: 控制序列化器的执行(检验.保存.转换数据) 控制数据库查询的执行 1.1. 请求与响应 1.1.1 Request RES ...

  9. APIView (DRF的视图)

    APIView和View的区别 -- APIView继承了View -- APIView 重写了as_view以及 dispatch方法 -- 在dispatch里重新封装了request  -- r ...

随机推荐

  1. VC 字符串转化和分割

    原文:点击这里. 备忘:为了适用于Unicode环境,要养成使用_T()宏的习惯 1.格式化字符串 CString s;s.Format(_T("The num is %d."), ...

  2. virtualBox下Centos系统扩展LVM磁盘空间

    工具准备:下载Gparted Live CD,一个分区管理工具(根据安装的32,64位版本选择对应链接).https://sourceforge.net/projects/gparted/files/ ...

  3. 用 CentOS 7 打造合适的科研环境

    这篇博文记录了我用 CentOS 7 搭建 地震学科研环境 的过程,供我个人在未来重装系统时参考.对于其他地震学科研人员,也许有借鉴意义. 阅读须知: 本文适用于个人电脑,不适用于服务器: 不推荐刚接 ...

  4. css3 - 特性

    伪类选择器 伪类选择器,不用再使用js来控制奇偶不同了 tr:nth-child(even){ background-color: white; } tr:nth-child(odd){ backgr ...

  5. package-info.java

    参考文章: http://blog.sina.com.cn/s/blog_93dc666c0101gzlr.html 对于package-info.java我们并不陌生,但又陌生. 在我们每次建立pa ...

  6. 集合,ArrayList

    用集合代替数组: Console.Write("请输入人数:"); int renshu = int.Parse(Console.ReadLine()); ArrayList ch ...

  7. es6初级之解构----之二 及 键值反转实现

    1.解构: 不定参数,扩展表达式 let arr = [100, 201, 303, 911]; let [one, ...others] = arr; console.log(others.leng ...

  8. ubuntu 该软件包现在的状态极为不妥 error

    rm -rf /var/lib/dpkg/info/yourerrorsofware* dpkg --remove --force-remove-reinstreq yourerrorsoftware ...

  9. Eclipce 配置javaEE

    Eclipse 安装JavaEE插件   Oxygen版Eclipse 导入项目会自动安装你项目需要的一些插件,但是有时候会安装失败,需要手动安装: 这里以Dynamic Web Project项目为 ...

  10. C++ 原来 const 中所使用的函数 必须 全都具有 const 才行

    今天在写程序的时候,出现了一个错误  "对象包含与成员函数不兼容的类型限定符",从网上查了一下,原来原因是这样子的 void showPair();改成 void showPair ...