序列化组件(get/put/delete接口设计),视图优化组件
一 . 知识点回顾
1 . 混入类 , 多继承
class Animal(object):
def eat(self):
print("Eat") def walk(self):
print("Walk") def sleep(self):
print("Sleep") def run(self):
print("Run") def flying(self):
print("Flying") def wangwang(self):
print("Wangwang") def miao(self):
print() class Dog(Animal):pass class Cat(Animal):pass class Bird(Animal):pass
可以看到,Dog类继承了Animal类,但是Dog并没有飞行和喵的功能,所以,如果直接继承Animal会有一些问题,请同学们思考,如何解决这个问题呢?
好了,其实我们有多中方式可以解决这个问题,比如:
class Animal(object):
def eat(self):
print("Eat") def walk(self):
print("Walk") def sleep(self):
print("Sleep") def run(self):
print("Run") class Flying(object):
def flying(self):
print("Flying") class WangWang(object):
def wangwang(self):
print("Wangwang") class Miao(object):
def miao(self):
print() class Dog(Animal, WangWang):pass class Cat(Animal, Miao):pass class Bird(Animal, Flying):pass
我们将不同的功能封装到了独立的类中,然后采用一种Mixin(混合类)的方式,其实也就是多继承,来解决这个问题,这在Python中是比较常见的解决方式,比如socketserver模块就用到了这种方式,当我们需要线程的时候,可以继承线程类,当我们需要进程的时候,可以继承进程类。
2 . 函数的参数
def func(a, b, c=1, *args, **kwargs):
print(a, b, c, args, kwargs) func(1, 2, 3, 4, 5) # 1, 2, 3, (4, 5) 所有未被匹配到的非key=value型的参数都会被*args接收
func(b=1, a=1, c=2, 4, 5) # 报错,位置参数不能在关键字参数之后
func(4, 5, c=3, {"name": "pizza"}) # 报错,位置参数不能在关键字参数之后,字典不是关键字参数
func({"name": "pizza"}, 1, 2) # {'name': 'pizza'} 1 2 () {}
func(1, 2, 3, 4, 5, d=1, e=2) # 1 2 3 (4, 5) {'d': 1, 'e': 2} 未被匹配到的关键字参数被传递给kwargs
二 . 序列化组件(get/put/delete接口设计)
基于上篇的表结构,通过序列化组件的 ModelSerializer 设计如下三个接口 :
GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{}
PUT 127.0.0.1:8000/books/{id} # 修改数据,返回值:{}
DELETE 127.0.0.1:8000/books/{id} # 删除数据,返回空
urls.py 文件
from django.urls import path, re_path
from serializer import views
urlpatterns = [
re_path('books/(\d+)/$', views.BookFilterView.as_view())
]
Views,py 文件 :
class BookFilterView(APIView):
def get(self, request, nid):
book_obj = Book.objects.get(pk=nid)
serialized_data = BookSerializer(book_obj, many=False)
return Response(serialized_data.data) def put(self, request, nid):
book_obj = Book.objects.get(pk=nid)
verified_data = BookSerializer(data=request.data, instance=book_obj, many=False)
if verified_data.is_valid():
verified_data.save()
return Response(verified_data.data)
else:
return Response(verified_data.errors) def delete(self, request, nid):
Book.objects.get(pk=nid).delete()
return Response()
PUT接口逻辑的设计,分为如下几个步骤:
- url设计:re_path(r’books/(\d+)/$’, views.BookFilterView.as_view())
- 视图类:重新定义一个视图类
- put方法:在视图类中定义一个put方法
- 序列化:在序列化的过程中,需要传入当前修改的数据行,参数名为instance
- 序列化类:不需要修改
- url路径:请求时,发送的url必须与urls.py中定义的url完全匹配
所以 , 加上上一篇的get和post接口,我们现在5个常用接口设计完成了,接口如下 :
class BookView(APIView):
def get(self, request):
origin_books = Book.objects.all()
serialized_books = BookSerializer(origin_books, many=True) return Response(serialized_books.data) def post(self, request):
verified_data = BookSerializer(data=request.data) if verified_data.is_valid():
book = verified_data.save()
return Response(verified_data.data)
else:
return Response(verified_data.errors) class BookFilterView(APIView):
def get(self, request, nid):
book_obj = Book.objects.get(pk=nid) serialized_data = BookSerializer(book_obj, many=False) return Response(serialized_data.data) def delete(self, request, nid):
book_obj = Book.objects.get(pk=nid).delete() return Response("") def put(self, request, nid):
book_obj = Book.objects.get(pk=nid) serialized_data = BookSerializer(data=request.data, instance=book_obj) if serialized_data.is_valid():
serialized_data.save()
return Response(serialized_data.data)
else:
return Response(serialized_data.errors)
两个视图类的接口逻辑
三 . 视图组件
前面的介绍中,我们已经通过序列化组件设计除了符合REST规范的五个常用接口,现在假设,我们有多个数据接口,比如(Book,Author,Publish...)等数据表都需要定义类似的接口,可以预见,我们需要重复定义类似上面的五个接口,这种方式将会导致大量的重复代码,显然,我们的程序还有很多需要优化的地方,那么,如果是你,将会如何进行优化呢?
这个时候,就需要我们的视图组件进行优化了!!!!!!
视图组件是用来优化接口逻辑的
视图组件的使用
1 . 使用视图组件的 mixin 进行接口逻辑优化 :
urls.py 代码 :
from django.urls import re_path
from serializer import views urlpatterns = [
re_path('books/$', views.BookView.as_view()),
re_path('books/(?P<pk>\d+)/$', views.BookFilterView.as_view()),
]
视图 views.py :
from rest_framework.mixins import (
ListModelMixin,
CreateModelMixin,
DestroyModelMixin,
UpdateModelMixin,
RetrieveModelMixin
)
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
# 导入序列化类
from .app_serializers import BookSerializer
from .models import Book, Publish, Author class BookView(ListModelMixin, CreateModelMixin, GenericAPIView):
# queryset和serializer_class是固定写法
queryset = Book.objects.all()
serializer_class = BookSerializer
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 BookFilterView(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs) def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs) def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
注意:单条数据操作的url有变化,因为我们在视图中,统一传的都是queryset,所以,需要通过传入一个名为pk的命名参数,告诉视图组件,用户需要操作的具体数据。
2 . 使用视图组件的 genericview 进行接口逻辑优化
上面的代码看似已经优化的非常完美了,但是,在一个对性能要求极高的项目里面,我们的程序还可以继续优化,不断优化程序是每个程序员必备的技能,也是帮助我们成长的重要手段。同样的思路,同样的方法,我们可以将多个接口封装到一个功能类中,如下代码:
views.py :
from rest_framework import generics from .app_serializers import BookSerializer
from .models import Book, Publish, Author class BookView(generics.ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer class BookFilterView(generics.RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
3 . 使用视图组件的 viewset 进行接口逻辑优化
上面的代码已经看似非常完美了,但是,你有没有发现还有重复代码,该如何改进呢?使用viewset可以进一步优化,如下:
urls.py文件(注意跟之前有什么不同)
from django.urls import re_path
from serializer import views urlpatterns = [
re_path('books/$', views.BookView.as_view({
'get': 'list',
'post': 'create'
})),
re_path('books/(?P<pk>\d+)/$', views.BookView.as_view({
'get': 'retrieve',
'put': 'update',
'delete': 'destroy'
}))
视图 views.py :
from rest_framework.viewsets import ModelViewSet
from .app_serializers import BookSerializer
from .models import Book, Publish, Author class BookView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
使用方式是不是很简单,接下来去看以下源码都为我们做了什么吧!其实整个viewset优化方案最重要的地方就是urls.py中传入了参数,然后对参数进行映射关系绑定。
viewset 源码剖析
- Django程序启动,开始初始化,读取urls.py, 读取settings, 读取视图类
- 执行as_views(), BookView没有,需要到父类(ModelViewSet)中找
- ModelViewSet继承了mixins的几个ModelMixin和GenericViewSet,显然ModelMixin也没有,只有GenericViewSet中有
- GenericViewSet没有任何代码,只继承了ViewSetMixin和generics.GenericAPIView(这个我们已经认识了)
- 继续去ViewSetMixin中查找,找到了as_view类方法,在重新封装view函数的过程中,有一个self.action_map = actions
- 这个actions就是我们给as_view()传递的参数
- 绑定url和视图函数(actions)之间的映射关系
- 等待用户请求
- 接收到用户请求,根据url找到视图函数
- 执行视图函数的dispatch方法(因为视图函数的返回值是:return self.dispatch()
- dispatch分发请求,查找到视图类的五个方法中的某个
- 开始执行,比如post请求,返回:self.create(),视图类本身没有,则会到父类中查找
- 最后在CreateModelMixin中查找
- 执行create()方法,获取queryset和serializer_class
- 返回数据
这就是viewset的优化方案,整个优化方案最重要的地方就是urls.py中我们传入的参数,然后对参数进行映射关系绑定。
序列化组件(get/put/delete接口设计),视图优化组件的更多相关文章
- DRF(3) - 序列化组件(GET/PUT/DELETE接口设计)、视图优化组件
一.序列化组件 基于上篇随笔的表结构,通过序列化组件的ModelSerializer设计如下三个接口: GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} PU ...
- DRF - 序列化组件(GET/PUT/DELETE接口设计)、视图优化组件
一.序列化组件 基于上篇随笔的表结构 , 通过序列化组件的ModelSerializer设计如下三个接口 : GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} ...
- Restful 3 -- 序列化组件(GET/PUT/DELETE接口设计)、视图优化组件
一.序列化组件 基于上篇随笔的表结构,通过序列化组件的ModelSerializer设计如下三个接口: GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} PU ...
- django rest framework 解析器组件 接口设计,视图组件 (2)
1. 使用视图组件进行接口优化 1.1 使用视图组件的mixin进行接口逻辑优化 - 导入mixin from rest_framework.mixinx import ( ListModelMix, ...
- django rest framework 解析器组件 接口设计,视图组件 (1)
一.解析器组件 -解析器组件是用来解析用户请求数据的(application/json), content-type 将客户端发来的json数据进行解析 -必须适应APIView -request.d ...
- DRF-->1 序列化组件的使用和接口设计---get
定义序列化器(本质就是一个类),一般包括模型类的字段,有自己的字段类型规则.实现了序列化器后,就可以创建序列化对象以及查询集进行序列化操作,通过序列化对象.data来获取数据(不用自己构造字典,再返回 ...
- DRF-->2序列化组件的使用和接口设计--get,post,put,delete&优化组件
!!!!! !!!!! 记住这个图 !!!!! 上篇博客说道DRF序列化组件的get,只是简单的举一个实例,然而在现实生活中我们前后端进行交互的时候更多的用到了Json数据格式,这也就是说前后端交互的 ...
- DRF(2) - 解析器,序列化组件使用(GET/POST接口设计)
一.DRF - 解析器 1.解析器的引出 我们知道,浏览器可以向django服务器发送json格式的数据,此时,django不会帮我们进行解析,只是将发送的原数据保存在request.body中,只有 ...
- Restful 2 --DRF解析器,序列化组件使用(GET/POST接口设计)
一.DRF - 解析器 1.解析器的引出 我们知道,浏览器可以向django服务器发送json格式的数据,此时,django不会帮我们进行解析,只是将发送的原数据保存在request.body中,只有 ...
随机推荐
- Linux 双网卡 不同网段 网络互通
环境如下: 现状:一台linux主机上有两个网卡eth0 和eth1 ,机器能访问192网的服务资源,但不能访问10网段的资源. 要求:linux能通过eth1访问10网段的资源 路由: 网卡: 操作 ...
- 判断vps类型
- django中日志使用学习记录
在setting中加入以下代码 LOGGING = { 'version': 1, 'disable_existing_loggers': True, 'formatters': { 'verbose ...
- git 指令如何撤销一次merge
在使用git指令时难免会发生错误的merge的情况,那么如何在这种情况下回退到错误发生之前的情况? git reflog 指令显示历史的操作 4457e43 HEAD@{0}: reset: movi ...
- Java架构师与开发者提高效率的10个工具
Java受到全球百万计开发者的追捧,已经演变为一门出色的编程语言.最终,这门语言随着技术的变化,不断的被改善以迎合变化的市场需求. 无论你是否拥有一家科技公司,软件已经成为几乎每一个企业不可或缺的一部 ...
- 如何选择Haproxy和Nginx
对于做软负载,我们都知道主流的方案有LVS.Haproxy.Nginx!那么对于Haproxy和Nginx,我们如何选择呢?回答这个问题之前,我根据个人使用经验来讲下它们的特点! Haproxy特点 ...
- mysql root密码忘记最快方法
在my.cnf [mysqld]栏添加 skip-grant-tables 然后重启/etc/init.d/mysqld restart mysql ##select password('新密码') ...
- apue学习笔记(第十四章 高级I/O)
本章涵盖了从多概念和函数:非阻塞I/O.记录锁.I/O多路转换.异步I/O.readv和writev函数以及存储映射I/O 非阻塞I/O 非阻塞I/O使我们可以发出open.read和write这样的 ...
- kettle转换之多线程
kettle转换之多线程 ETL项目中性能方面的考虑一般是最重要的.特别是所讨论的任务频繁运行,或一些列的任务必须在固定的时间内运行.本文重点介绍利用kettle转换的多线程特性.以优化其性能. ...
- layui-概念-入门-总结
layui教程:http://www.dosrun.com/layui/ 获得 Layui你可以在官网首页下载到 Layui 的最新版,也可以通过 GitHub得到Layui的开源包.目前只同步维护这 ...