前戏
在前面几篇文章里,我们写了get请求,post请求,put请求,在来写个delete请求,大概如下。
class BookView(APIView): # 查询所有的数据和post方法 def get(self, request): book_queryset = Book.objects.all() # 拿出来的是一个queryset,用序列化器进行序列化 ser_obj = BookSerializer(book_queryset, many=True) return Response(ser_obj.data) # 序列化后的数据在data里 def post(self, request): # 确定数据类型以及数据结构 # 对前端传来的数据进行校验 book_obj = request.data # post传来的数据 ser_obj = BookSerializer(data=book_obj) # 有data参数,表示反序列化 if ser_obj.is_valid(): ser_obj.save() return Response(ser_obj.validated_data) return Response(ser_obj.errors) # 返回错误 class BookEditView(APIView): # 查询单条数据和put、delete方法 def get(self, request, id): book_obj = Book.objects.filter(id=id).first() ser_obj = BookSerializer(book_obj) # 查询出的是一条数据,不需要加 many=True return Response(ser_obj.data) def put(self, request, id): book_obj = Book.objects.filter(id=id).first() # instance必传,data=request.data前端传的参数,partial=True部分修改 ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True) if ser_obj.is_valid(): ser_obj.save() return Response(ser_obj.data) # 返回数据,注意不是ser_obj.validated_data return Response(ser_obj.errors) def delete(self, request, id): book_obj = Book.objects.filter(id=id).first() if not book_obj: return Response('删除的对象不存在') book_obj.delete() return Response('Success')
路由
urlpatterns = [ url(r'^book/$', BookView.as_view()), url(r'^book/(?P<id>\d+)', BookEditView.as_view()), ]
这个视图只是实现了Book表的增删改查功能,如果有几十张表,我们就要写几十个对应的类,复制,粘贴,复制,粘贴。。。身为一个优秀的测试工程师。这种比较low的方法肯定不是我们干的,应该是开发干的,手动滑稽。
如果分析上面的代码,我们会发现,每个请求只要传不同的ORM语句和序列化器就可以实现了。所以我们可以对代码进行重构,面向对象的三大特性,继承,封装,多态。我们可以写一个通用的方法来继承它,每个子类都可以改写继承过来的方法,就是多态。
第一版
1 from django.shortcuts import render 2 from rest_framework.views import APIView 3 from rest_framework.response import Response 4 from djangoDemo.models import Book # 导入表 5 from .serializers import BookSerializer 6 7 8 class GenericAPIView(APIView): # 通用的API视图 9 queryset = None 10 serializer_class = None 11 12 def get_queryset(self): 13 # 这里要加.all() 虽然下面的ORM查询出来的是所有的数据 14 # 但是由于DRF的内部机制,这里如果不加就会报错 15 return self.queryset.all() 16 17 def get_serializer(self, *args, **kwargs): 18 # 不同请求的序列化器里传的参数是不一样的 19 return self.serializer_class(*args, **kwargs) 20 21 22 class BookView(GenericAPIView): # 继承通用的方法 23 queryset = Book.objects.all() 24 serializer_class = BookSerializer 25 26 def get(self, request): 27 # 调用外部的get方法 28 queryset = self.get_queryset() 29 30 # 调用外部的序列化方法 31 ser_obj = self.get_serializer(queryset, many=True) 32 return Response(ser_obj.data) 33 34 def post(self, request): 35 ser_obj = self.get_serializer(data=request.data) 36 if ser_obj.is_valid(): 37 ser_obj.save() 38 return Response(ser_obj.validated_data) 39 return Response(ser_obj.errors)
当上面的代码执行get请求时,先执行28行,28行调用的是12,执行15行,返回的是一个queryset,然后先在自己内部找,自己内部有,也就是23行,在执行31行,调用的是17行,执行19行,返回的是serializer_class,先在自己内部找,自己内部有,也就是24行。在执行32行
上面的代码只是简单的封装了一下,还可以在次封装。
第二版
1 from django.shortcuts import render 2 from rest_framework.views import APIView 3 from rest_framework.response import Response 4 from djangoDemo.models import Book # 导入表 5 from .serializers import BookSerializer 6 7 8 class GenericAPIView(APIView): # 通用的API视图 9 queryset = None 10 serializer_class = None 11 12 def get_queryset(self): 13 # 这里要加.all() 虽然下面的ORM查询出来的是所有的数据 14 # 但是由于DRF的内部机制,这里如果不加就会报错 15 return self.queryset.all() 16 17 def get_serializer(self, *args, **kwargs): 18 # 不同请求的序列化器里传的参数是不一样的 19 return self.serializer_class(*args, **kwargs) 20 21 class ListModelMixin(object): # get方法,查询所有数据 22 def list(self, request): 23 queryset = self.get_queryset() 24 ser_obj = self.get_serializer(queryset, many=True) 25 return Response(ser_obj.data) 26 27 class CreateModelMixin(object): # post方法 28 def create(self, request): 29 ser_obj = self.get_serializer(data=request.data) 30 if ser_obj.is_valid(): 31 ser_obj.save() 32 return Response(ser_obj.validated_data) 33 return Response(ser_obj.errors) 34 35 36 class BookView(GenericAPIView, ListModelMixin, CreateModelMixin): # 继承 37 queryset = Book.objects.all() 38 serializer_class = BookSerializer 39 40 def get(self, request): 41 return self.list(request) # 调用get方法 42 43 def post(self, request): 44 return self.create(request) # 调用post方法
上面对BookView类进行了封装处理,还有一个BookEditView类,也来进行封装处理
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 class GenericAPIView(APIView): # 通用的API视图 queryset = None serializer_class = None def get_queryset(self): # 这里要加.all() 虽然下面的ORM查询出来的是所有的数据 # 但是由于DRF的内部机制,这里如果不加就会报错 return self.queryset.all() def get_serializer(self, *args, **kwargs): # 不同请求的序列化器里传的参数是不一样的 return self.serializer_class(*args, **kwargs) class RetrieveModelMixin(object): # get方法,查询单条数据 def retrieve(self, request, id): # 先查询出所有,在过滤,在取第一个 book_obj = self.get_queryset().filter(id=id).first() ser_obj = self.get_serializer(book_obj) return Response(ser_obj.data) class UpdateModelMixin(object): # put方法 def update(self, request, id): book_obj = self.get_queryset().filter(id=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.data) # 返回数据,注意不是ser_obj.validated_data return Response(ser_obj.errors) class DestroyModelMixin(object): # delete方法 def destoy(self, request, id): book_obj = self.get_queryset().filter(id=id).first() if not book_obj: return Response('删除的对象不存在') book_obj.delete() return Response('Success') class BookEditView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin): # 查询单条数据和put、delete方法 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.destoy(request, id)
这样我们就完成了所有请求的封装
在来看下,每个BookView类和BookEditView类都继承了好几个类,如果以后还有其他的类,都要继承这几个类,多麻烦,我们可以写两个单独的类,来继承,以后所有的类都继承这两个类就可以了