视图和路由

  1. 视图封装

  • 第一次封装

​ 上一篇最后我们对书籍表做了增删改查,那么如果现在我们有几十上百张表需要这样做呢?我们知道类的特性有封装,因此我们可以尝试进行封装下.

  1. from rest_framework.views import APIView
  2. from rest_framework.response import Response
  3.  
  4. from .models import Book
  5. from .modelSerializers import BookModelSerializer
  6.  
  7. class GenericAPIView(APIView):
  8. queryset = None
  9. serializer_class = None
  10.  
  11. def get_queryset(self):
  12. return self.queryset.all()
  13.  
  14. def get_serializer(self, *args, **kwargs):
  15. return self.serializer_class(*args, **kwargs)
  16.  
  17. class ListModelMixin(object):
  18. # 这个就是把get方法抽离了出来,变成了list方法
  19. def list(self, request, *args, **kwargs):
  20. queryset = self.get_queryset()
  21. serializer_data = self.get_serializer(queryset, many=True)
  22. return Response(serializer_data.data)
  23.  
  24. class CreateModelMixin(object):
  25. def create(self, request, *args, **kwargs):
  26. ser_obj = self.get_serializer(data=request.data)
  27. if ser_obj.is_valid():
  28. ser_obj.save()
  29. return Response(ser_obj.validated_data)
  30. return Response(ser_obj.errors)
  31.  
  32. class RetrieveModelMixin(object):
  33. def retrieve(self, request, id, *args, **kwargs):
  34. book_obj = self.get_queryset().filter(pk=id).first()
  35. ser_obj = self.get_serializer(book_obj)
  36. return Response(ser_obj.data)
  37.  
  38. class UpdateModelMixin(object):
  39. def update(self, request, id, *args, **kwargs):
  40. book_obj = self.get_queryset().filter(pk=id).first()
  41. ser_obj = self.get_serializer(instance=book_obj, data=request.data, partial=True)
  42. if ser_obj.is_valid():
  43. ser_obj.save()
  44. return Response(ser_obj.validated_data)
  45. return Response(ser_obj.errors)
  46.  
  47. class DestroyModeMixin(object):
  48. def destroy(self, request, id , *args, **kwargs):
  49. book_obj = self.get_queryset().filter(id=id).first()
  50. if not book_obj:
  51. return Response("要删除的对象不存在")
  52. book_obj.delete()
  53. return Response("")
  54.  
  55. class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
  56. pass
  57.  
  58. class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModeMixin):
  59. pass
  60.  
  61. class BookView(ListCreateAPIView):
  62. """书籍相关视图"""
  63. queryset = Book.objects
  64. serializer_class = BookModelSerializer
  65.  
  66. def get(self, request, *args, **kwargs):
  67. return self.list(request, *args, **kwargs)
  68.  
  69. def post(self, request, *args, **kwargs):
  70. return self.create(request, *args, **kwargs)
  71.  
  72. class BookEditView(RetrieveUpdateDestroyAPIView):
  73. queryset = Book.objects
  74. serializer_class = BookModelSerializer
  75.  
  76. def get(self, request, id, *args, **kwargs):
  77. return self.retrieve(request, id, *args, **kwargs)
  78.  
  79. def put(self, request, id, *args, **kwargs):
  80. return self.update(request, id, *args, **kwargs)
  81.  
  82. def delete(self, request, id, *args, **kwargs):
  83. return self.destroy(request, id, *args, **kwargs)

​ 从上面我们可以知道,我们发现视图中就只有query和ModelSerializer每个方法不一样,因此,我们先定义了一个GenericAPIView,该方法就是专门获取query和ModelSerializer.再接着就是将get全部/get单条/post/put/delete方法分别再次封装到不同类中的方法中,这样在写多个表时只需要调用方法即可,但是此时你会发现继承的类有点长,因此又封装了两个类专门继承多个类,这样我们再写就只需要继承一个类了,你看这样是不是变得更简单了,我们必须学习这种封装的思想,使得自己代码更加简洁,复用性更高.

  • 二次最终封装

    上面封装似乎已经很好了,但是人总是贪婪的,上面是不是定义了两个视图针对不同操作(BookView和BookEditView),那我们想能不能只定义一个视图就完成呢?此时我们去看一下rest_framework提供的源码

    在这里先被备注下rest_framework给我们的几个视图相关的类

    1. from rest_framework import views # 里面主要是有APIView
    2. from rest_framework import viewsets # ModelViewSet封装,继承mixins下的各个类
    3. from rest_framework import generics # GenericAPIView,CreateAPIView等封装
    4. from rest_framework import mixins # list,create,update等方法具体实现

    因为我们需要合并视图,所以我们需要在as_view()时出入对应关系的参数,所以我们看下viewsets下的ViewSetMixin类, from rest_framework.viewsets import ViewSetMixin.

    从ViewSetMixin中我们可以知道,重写了as_view()方法,并且将参数传给了action,这里我只拿出了一些需要的代码进行说明下.

    1. def as_view(cls, actions=None, **initkwargs):
    2. # actions = {"get": "list", "post": "create"}
    3. def view(request, *args, **kwargs):
    4. for method, action in actions.items():
    5. # method = get, action = list
    6. handler = getattr(self, action)
    7. # 这里就将self.get = self.list,所以之后get请求就会去找list方法
    8. setattr(self, method, handler)
    所以注意下,只有继承了ViewSetMixin路由才可以传参,前面说完了,我们来再次封装下代码:

    views下就变成了

    1. class ModelViewSet(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
    2. pass
    3.  
    4. class BooksView(ModelViewSet):
    5. queryset = Book.objects
    6. serializer_class = BookModelSerializer

    urls下变成

    1. path('books', views.BooksView.as_view({"get": "list", "post": "create"})),
    2. re_path('book/(?P<id>\d+)', views.BooksView.as_view({"get": "retrieve", "patch": "update", "delete": "destroy"})),

    其实我们辗转了大半天,人家早就给我们封装好了,views下我们啥都不用写,就只需要继承人家封装好的就可以了,就下面几行代码即可

  • DRF视图最终写法
    1. from rest_framework import viewsets
    2. class BooksView(viewsets.ModelViewSet):
    3. queryset = Book.objects
    4. serializer_class = BookModelSerializer

    但是urls那里不能写id了,只能写pk

    1. path('books', views.BooksView.as_view({"get": "list", "post": "create"})),
    2. re_path('book/(?P<pk>\d+)', views.BooksView.as_view({"get": "retrieve", "patch": "update", "delete": "destroy"})),
  1. DRF路由

    思考下,如果我们要写几十张表的路由,那岂不是又要每个路由传一堆一样的参数?别怕,DRF又帮我们搞定了,我们只需要按照下面的方式写即可

    1. from rest_framework.routers import DefaultRouter
    2.  
    3. # 实例化DefaultRouter
    4. router = DefaultRouter()
    5. # 注册路由以及视图
    6. router.register(r"book", views.BooksView)
    7.  
    8. # 将路由url加入到urlpatterns
    9. urlpatterns += router.urls

    该方法虽然简洁快速,但也会暴露很多路由接口,视情况选择使用.

Django REST Framework(DRF)_第二篇的更多相关文章

  1. Django REST Framework(DRF)_第一篇

    认识RESTful REST是设计风格而不是标准,简单来讲REST规定url是用来唯一定位资源,而http请求方式则用来区分用户行为. REST接口设计规范 HTTP常用动词 GET /books:列 ...

  2. Django REST Framework(DRF)_第四篇

    DRF分页(总共三种) PageNumberPagination(指定第n页,每页显示n条数据) 说明 既然要用人家的那么我们就先来看下源码,这个分页类源码中举例通过参数指定第几页和每页显示的数据:h ...

  3. Django REST Framework(DRF)_第三篇

    DRF版本控制 介绍 我们在看APIView源码时可以看到,版本和版本控制类是通过determine_version的返回值获取的 version, scheme = self.determine_v ...

  4. Django 学习之Django Rest Framework(DRF)

    一. WEB应用模式 在开发Web应用中,有两种应用模式 1. 前后端不分离 把html模板文件和django的模板语法结合渲染完成以后才从服务器返回给客户. 2. 前后端分离 二. API接口 AP ...

  5. day71:drf:API接口&Restful API规范&Django Rest Framework&drf中的序列化和反序列化功能

    目录 1.web应用模式 2.API接口 3.Restful API规范 4.序列化 5.Django Rest Framework 1.drf的简单介绍 2.drf的特点 3.如何安装drf 4.d ...

  6. Matlab高级教程_第二篇:关于MATLAB转C#过程中遇到输出两组参数的问题

    1. 在matlab的m函数很可能遇到原函数[a,b] = func(a); 这样的两个输出参数. 2. 在观察C#生成后定义中我们发现: public MWArray HP(); public MW ...

  7. Python全栈开发记录_第二篇(文件操作及三级菜单栏增删改查)

    python3文件读写操作(本篇代码大约100行) f = open(xxx.txt, "r", encoding="utf-8") 不写“r”(只读)默认是只 ...

  8. Python笔记_第二篇_面向过程_第二部分_2.路径、栈和队列、内存修改

    这一部分分三个主题进行讲解,主要为后面的模块.包.第三方库的概念补充一些相关的内容. 1. 路径(Path): 相对路径和绝对路径. 举例1:我们先导入一个os库(模块)来观察一下路径 import ...

  9. Matlab高级教程_第二篇:Matlab相见恨晚的模块_02_并行运算-1

    1 更高级的算法牵扯到更多重的循环和复杂的计算,尤其是现在人工智能的算法尤其如此.有些历史知识的人能够了解到,人工智能的很多基本算法其实近百年之前就有了,但是当时的计算机技术达不到去实现这些算法的要求 ...

随机推荐

  1. linux log rotate

    今天老大提醒我产线kafka自身的log文件积累了好几个月了,我才发现原来kafka的log4j并删除old log. 第一反应是采用linux自带的logrotate功能,在/etc/logrota ...

  2. 关于JDK和JRE的一些总结

    一.关于JDK和JRE JDK (Java Development Kit)即java开发工具,包括JER及代码编译器(javac).文档注释器(JavaDoc).代码调试器(Java Debugge ...

  3. 搭建RPC over HTTP 环境遇到的问题

    最近需要做RPC的IPS协议分析,需要了解一下RPC over HTTP的协议格式,由于此类数据包不易构造,故此想搭建一个抓一些包分析一下. 结果搭建这么个环境硬是用了我四个工作日的时间,崩溃加无语. ...

  4. 八大排序算法 JAVA实现 亲自测试 可用!

    今天很高兴 终于系统的实现了八大排序算法!不说了 直接上代码 !代码都是自己敲的, 亲测可用没有问题! 另:说一下什么是八大排序算法: 插入排序 希尔排序 选择排序 堆排序 冒泡排序 快速排序 归并排 ...

  5. 【简单脚本】Linux查看配置信息

    命令比较多,统一整合了一下: 1.新建文件touch getComputerConf.sh 2.vim getComputerConf.sh 3.按i键插入,右键粘贴如下内容: #!/bin/sh e ...

  6. css之vw布局

    vw,vh是视口单位,是相对视口单位,与百分百布局不一样的是,百分百是相对于父及元素,而vw布局是相对与窗口. 而rem布局是要与js一起配合 // 以iphone6设计稿 @function px2 ...

  7. mysql产生死锁

    select * from information_schema.innodb_trx; kill 对应线程ID show PROCESSLIST;

  8. python模块之:paramiko

    1. 介绍: paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来实现.安装: ...

  9. Python笔记【6】_函数

    #!/usr/bin/env/python #-*-coding:utf-8-*- #Author:LingChongShi #查看源码Ctrl+左键 ''' def:函数是一段可以重复调用的代码,通 ...

  10. 一文学会Java死锁和CPU 100% 问题的排查技巧

    做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开 工欲善其事,必先利其器 00 本文简介 作为一名搞技术的程序猿或者是攻城狮,想必你应该是对下面这两个问题有所了解,说不定你在 ...