Django REST Framework(DRF)_第二篇
视图和路由
视图封装
第一次封装
上一篇最后我们对书籍表做了增删改查,那么如果现在我们有几十上百张表需要这样做呢?我们知道类的特性有封装,因此我们可以尝试进行封装下.
- from rest_framework.views import APIView
- from rest_framework.response import Response
- from .models import Book
- from .modelSerializers import BookModelSerializer
- class GenericAPIView(APIView):
- queryset = None
- serializer_class = None
- def get_queryset(self):
- return self.queryset.all()
- def get_serializer(self, *args, **kwargs):
- return self.serializer_class(*args, **kwargs)
- class ListModelMixin(object):
- # 这个就是把get方法抽离了出来,变成了list方法
- def list(self, request, *args, **kwargs):
- queryset = self.get_queryset()
- serializer_data = self.get_serializer(queryset, many=True)
- return Response(serializer_data.data)
- class CreateModelMixin(object):
- def create(self, request, *args, **kwargs):
- ser_obj = self.get_serializer(data=request.data)
- if ser_obj.is_valid():
- ser_obj.save()
- return Response(ser_obj.validated_data)
- return Response(ser_obj.errors)
- class RetrieveModelMixin(object):
- def retrieve(self, request, id, *args, **kwargs):
- book_obj = self.get_queryset().filter(pk=id).first()
- ser_obj = self.get_serializer(book_obj)
- return Response(ser_obj.data)
- class UpdateModelMixin(object):
- def update(self, request, id, *args, **kwargs):
- book_obj = self.get_queryset().filter(pk=id).first()
- ser_obj = self.get_serializer(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 DestroyModeMixin(object):
- def destroy(self, request, id , *args, **kwargs):
- book_obj = self.get_queryset().filter(id=id).first()
- if not book_obj:
- return Response("要删除的对象不存在")
- book_obj.delete()
- return Response("")
- class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
- pass
- class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModeMixin):
- pass
- class BookView(ListCreateAPIView):
- """书籍相关视图"""
- queryset = Book.objects
- serializer_class = BookModelSerializer
- def get(self, request, *args, **kwargs):
- return self.list(request, *args, **kwargs)
- def post(self, request, *args, **kwargs):
- return self.create(request, *args, **kwargs)
- class BookEditView(RetrieveUpdateDestroyAPIView):
- queryset = Book.objects
- serializer_class = BookModelSerializer
- def get(self, request, id, *args, **kwargs):
- return self.retrieve(request, id, *args, **kwargs)
- def put(self, request, id, *args, **kwargs):
- return self.update(request, id, *args, **kwargs)
- def delete(self, request, id, *args, **kwargs):
- return self.destroy(request, id, *args, **kwargs)
从上面我们可以知道,我们发现视图中就只有query和ModelSerializer每个方法不一样,因此,我们先定义了一个GenericAPIView,该方法就是专门获取query和ModelSerializer.再接着就是将get全部/get单条/post/put/delete方法分别再次封装到不同类中的方法中,这样在写多个表时只需要调用方法即可,但是此时你会发现继承的类有点长,因此又封装了两个类专门继承多个类,这样我们再写就只需要继承一个类了,你看这样是不是变得更简单了,我们必须学习这种封装的思想,使得自己代码更加简洁,复用性更高.
二次最终封装
上面封装似乎已经很好了,但是人总是贪婪的,上面是不是定义了两个视图针对不同操作(BookView和BookEditView),那我们想能不能只定义一个视图就完成呢?此时我们去看一下rest_framework提供的源码
在这里先被备注下rest_framework给我们的几个视图相关的类
- from rest_framework import views # 里面主要是有APIView
- from rest_framework import viewsets # ModelViewSet封装,继承mixins下的各个类
- from rest_framework import generics # GenericAPIView,CreateAPIView等封装
- from rest_framework import mixins # list,create,update等方法具体实现
因为我们需要合并视图,所以我们需要在as_view()时出入对应关系的参数,所以我们看下viewsets下的ViewSetMixin类, from rest_framework.viewsets import ViewSetMixin.
从ViewSetMixin中我们可以知道,重写了as_view()方法,并且将参数传给了action,这里我只拿出了一些需要的代码进行说明下.
- def as_view(cls, actions=None, **initkwargs):
- # actions = {"get": "list", "post": "create"}
- def view(request, *args, **kwargs):
- for method, action in actions.items():
- # method = get, action = list
- handler = getattr(self, action)
- # 这里就将self.get = self.list,所以之后get请求就会去找list方法
- setattr(self, method, handler)
所以注意下,只有继承了ViewSetMixin路由才可以传参,前面说完了,我们来再次封装下代码:
views下就变成了
- class ModelViewSet(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
- pass
- class BooksView(ModelViewSet):
- queryset = Book.objects
- serializer_class = BookModelSerializer
urls下变成
- path('books', views.BooksView.as_view({"get": "list", "post": "create"})),
- re_path('book/(?P<id>\d+)', views.BooksView.as_view({"get": "retrieve", "patch": "update", "delete": "destroy"})),
其实我们辗转了大半天,人家早就给我们封装好了,views下我们啥都不用写,就只需要继承人家封装好的就可以了,就下面几行代码即可
- from rest_framework import views # 里面主要是有APIView
DRF视图最终写法
- from rest_framework import viewsets
- class BooksView(viewsets.ModelViewSet):
- queryset = Book.objects
- serializer_class = BookModelSerializer
但是urls那里不能写id了,只能写pk
- path('books', views.BooksView.as_view({"get": "list", "post": "create"})),
- re_path('book/(?P<pk>\d+)', views.BooksView.as_view({"get": "retrieve", "patch": "update", "delete": "destroy"})),
- from rest_framework import viewsets
DRF路由
思考下,如果我们要写几十张表的路由,那岂不是又要每个路由传一堆一样的参数?别怕,DRF又帮我们搞定了,我们只需要按照下面的方式写即可
- from rest_framework.routers import DefaultRouter
- # 实例化DefaultRouter
- router = DefaultRouter()
- # 注册路由以及视图
- router.register(r"book", views.BooksView)
- # 将路由url加入到urlpatterns
- urlpatterns += router.urls
该方法虽然简洁快速,但也会暴露很多路由接口,视情况选择使用.
Django REST Framework(DRF)_第二篇的更多相关文章
- Django REST Framework(DRF)_第一篇
认识RESTful REST是设计风格而不是标准,简单来讲REST规定url是用来唯一定位资源,而http请求方式则用来区分用户行为. REST接口设计规范 HTTP常用动词 GET /books:列 ...
- Django REST Framework(DRF)_第四篇
DRF分页(总共三种) PageNumberPagination(指定第n页,每页显示n条数据) 说明 既然要用人家的那么我们就先来看下源码,这个分页类源码中举例通过参数指定第几页和每页显示的数据:h ...
- Django REST Framework(DRF)_第三篇
DRF版本控制 介绍 我们在看APIView源码时可以看到,版本和版本控制类是通过determine_version的返回值获取的 version, scheme = self.determine_v ...
- Django 学习之Django Rest Framework(DRF)
一. WEB应用模式 在开发Web应用中,有两种应用模式 1. 前后端不分离 把html模板文件和django的模板语法结合渲染完成以后才从服务器返回给客户. 2. 前后端分离 二. API接口 AP ...
- 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 ...
- Matlab高级教程_第二篇:关于MATLAB转C#过程中遇到输出两组参数的问题
1. 在matlab的m函数很可能遇到原函数[a,b] = func(a); 这样的两个输出参数. 2. 在观察C#生成后定义中我们发现: public MWArray HP(); public MW ...
- Python全栈开发记录_第二篇(文件操作及三级菜单栏增删改查)
python3文件读写操作(本篇代码大约100行) f = open(xxx.txt, "r", encoding="utf-8") 不写“r”(只读)默认是只 ...
- Python笔记_第二篇_面向过程_第二部分_2.路径、栈和队列、内存修改
这一部分分三个主题进行讲解,主要为后面的模块.包.第三方库的概念补充一些相关的内容. 1. 路径(Path): 相对路径和绝对路径. 举例1:我们先导入一个os库(模块)来观察一下路径 import ...
- Matlab高级教程_第二篇:Matlab相见恨晚的模块_02_并行运算-1
1 更高级的算法牵扯到更多重的循环和复杂的计算,尤其是现在人工智能的算法尤其如此.有些历史知识的人能够了解到,人工智能的很多基本算法其实近百年之前就有了,但是当时的计算机技术达不到去实现这些算法的要求 ...
随机推荐
- linux log rotate
今天老大提醒我产线kafka自身的log文件积累了好几个月了,我才发现原来kafka的log4j并删除old log. 第一反应是采用linux自带的logrotate功能,在/etc/logrota ...
- 关于JDK和JRE的一些总结
一.关于JDK和JRE JDK (Java Development Kit)即java开发工具,包括JER及代码编译器(javac).文档注释器(JavaDoc).代码调试器(Java Debugge ...
- 搭建RPC over HTTP 环境遇到的问题
最近需要做RPC的IPS协议分析,需要了解一下RPC over HTTP的协议格式,由于此类数据包不易构造,故此想搭建一个抓一些包分析一下. 结果搭建这么个环境硬是用了我四个工作日的时间,崩溃加无语. ...
- 八大排序算法 JAVA实现 亲自测试 可用!
今天很高兴 终于系统的实现了八大排序算法!不说了 直接上代码 !代码都是自己敲的, 亲测可用没有问题! 另:说一下什么是八大排序算法: 插入排序 希尔排序 选择排序 堆排序 冒泡排序 快速排序 归并排 ...
- 【简单脚本】Linux查看配置信息
命令比较多,统一整合了一下: 1.新建文件touch getComputerConf.sh 2.vim getComputerConf.sh 3.按i键插入,右键粘贴如下内容: #!/bin/sh e ...
- css之vw布局
vw,vh是视口单位,是相对视口单位,与百分百布局不一样的是,百分百是相对于父及元素,而vw布局是相对与窗口. 而rem布局是要与js一起配合 // 以iphone6设计稿 @function px2 ...
- mysql产生死锁
select * from information_schema.innodb_trx; kill 对应线程ID show PROCESSLIST;
- python模块之:paramiko
1. 介绍: paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来实现.安装: ...
- Python笔记【6】_函数
#!/usr/bin/env/python #-*-coding:utf-8-*- #Author:LingChongShi #查看源码Ctrl+左键 ''' def:函数是一段可以重复调用的代码,通 ...
- 一文学会Java死锁和CPU 100% 问题的排查技巧
做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开 工欲善其事,必先利其器 00 本文简介 作为一名搞技术的程序猿或者是攻城狮,想必你应该是对下面这两个问题有所了解,说不定你在 ...