不使用drf视图
#在下面的这些代码中,存在很多代码重复 from rest_framework.views import APIView from app01.models import * from app01.mySer import * from django.http import JsonResponse class PublishView(APIView): def get(self, request): #获取所有数据 publish_list = Publish.objects.all() bs = PublishSerializers(publish_list, many=True) #PublishSerializers自己写的序列化 return JsonResponse(bs.data,safe=False) def post(self, request): #添加纪录 # 添加一条数据 print(request.data) bs = PublishSerializers(data=request.data) if bs.is_valid(): bs.save() # 生成记录 return JsonResponse(bs.data,safe=False) else: return JsonResponse(bs.errors,safe=False) class PublishDetailView(APIView): def get(self, request, pk): #获取单条数据 publish_obj = Publish.objects.filter(pk=pk).first() bs = PublishSerializers(publish_obj, many=False) return JsonResponse(bs.data,safe=False) def put(self, request, pk): #修改单条 publish_obj = Publish.objects.filter(pk=pk).first() bs = PublishSerializers(data=request.data, instance=publish_obj) if bs.is_valid(): bs.save() # update return JsonResponse(bs.data) else: return JsonResponse(bs.errors) def delete(self, request, pk): #删除一条数据 Publish.objects.filter(pk=pk).delete() return JsonResponse("")
还是不使用drf,但进行了封装
#自己写两个类,把重复代码抽出来 class List: #列表,拿多条 #把获取多条的get抽过来 def list(self): publish_list = Publish.objects.all() bs = PublishSerializers(publish_list, many=True) # PublishSerializers自己写的序列化 return JsonResponse(bs.data, safe=False) class Create: #把post方法抽过来 def create(self,request): bs = PublishSerializers(data=request.data) if bs.is_valid(): bs.save() # 生成记录 return JsonResponse(bs.data, safe=False) else: return JsonResponse(bs.errors, safe=False) ------------------------------------------------------------ #使用的时候 class PublishView(APIView,List,Create): def get(self, request): # 获取所有数据 return self.list(request) #当请求来到这时,在当前找不到list方法,然后去父类找,执行,并拿到结果 def post(self, request): return self.create(request)#同理,请求来了,去父类中找create方法 --------------------------------------------------- #但是 #上面这种方式只能对应Publish表,PublishSerializers序列化组件,写死了 class BookhView(APIView, List, Create) # def get(self, request): return self.list(request) def post(self, request): return self.create(request)
#把写死的地方,通过传值写活 class List: #列表,拿多条 def list(self): #把获取多条的get抽过来 # publish_list = Publish.objects.all() #原来的方式 # bs = PublishSerializers(publish_list, many=True queryset = self.queryset #把原本写死的东西写活 bs = self.serializers(queryset, many=True) #把原本写死的东西写活 return JsonResponse(bs.data, safe=False) class Create: def create(self,request): #把post方法抽过来 print(request.data) # bs = PublishSerializers(data=request.data) bs = self.serializers(data=request.data) #把原本写死的东西写活 if bs.is_valid(): bs.save() # 生成记录 return JsonResponse(bs.data, safe=False) else: return JsonResponse(bs.errors, safe=False) ------------------------------------------- #使用 class PublishView(APIView,List,Create): #前边自己写的两个类,是怎么处理,一定要与这里的怎么用区分开,条理清晰 queryset= Publish.objects.all() #需要用哪个模型表,就传给queryset serializers=PublishSerializers #需要用哪个序列化组件,就把谁赋给serializers def get(self, request): # 获取所有数据 return self.list(request) #当请求来到这时,在当前找不到list方法,然后去父类找,执行,并拿到结果 def post(self, request): return self.create(request)#同理,请求来了,去父类中找create方法 class BookhView(APIView, List, Create) #此时就比较方便了,再来多少都行,只需要把模型表 queryset= Book.objects.all() #需要用哪个模型表,就传给queryset serializers=BookSerializers #需要用哪个序列化组件,就把谁赋给serializers def get(self, request): return self.list(request) def post(self, request): return self.create(request)
使用drf封装的类
先看源码(拿两个典型的,其他的类似)
#GenericAPIView它继承了APIView,只不过添加了一些方法 其他几个类要基于它使用, class GenericAPIView(views.APIView): queryset = None serializer_class = None lookup_field = 'pk' lookup_url_kwarg = None filter_backends = api_settings.DEFAULT_FILTER_BACKENDS pagination_class = api_settings.DEFAULT_PAGINATION_CLASS def get_queryset(self): def get_object(self): def get_serializer(self, *args, **kwargs): def get_serializer_class(self) def get_serializer_context(self) def filter_queryset(self, queryset)
class ListModelMixin(object): def list(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset()) #类似于自己写的queryset page = self.paginate_queryset(queryset) #分页相关 if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True) return Response(serializer.data) queryset #这些都需要去GenericAPIView中 get_queryset filter_queryset
使用
#GenericAPIView继承了APIView,只不过添加了几个方法 #拿多个 class PublishView(GenericAPIView,ListModelMixin,CreateModelMixin): queryset= Publish.objects.all() serializer_class=PublishSerializers def get(self, request): return self.list(request) #请求来到这里,list方法,自己,没有,去父类,在ListModelMixin中找到,父类中需要的 filter_queryset,paginate_queryset,get_serializer先来自己这找,自己这没有,去父类中,在GenericAPIView中找到 def post(self, request): #添加用CreateModelMixin return self.create(request) #同样道理,create去父类中找,父类中需要的其他参数,去另外父类中找 --------------------------------------------------------- #拿一个的方法,道理同上 from rest_framework.mixins import ListModelMixin,RetrieveModelMixin,RetrieveModelMixin,DestroyModelMixin from rest_framework.generics import GenericAPIView class PublishDetailView(APIView): queryset= Publish.objects.all() serializer_class=PublishSerializers def get(self, request,pk): #RetrieveModelMixin return self.retrieve(self, request, pk) def post(self, request,pk): #RetrieveModelMixin return self.update(request,pk) def delete(self, request, pk): #DestroyModelMixin return self.destroy(request,pk) ------------------------------------------ #这种方法仍然存在重复代码,取多个,取一个都要指定 queryset= Publish.objects.all() serializer_class=PublishSerializers
使用drf升级版(最终版)
# 上面发现仍有重复代码 # queryset = Publish.objects.all() # serializers = PublishSerializers
from rest_framework.viewsets import ModelViewSet class PublishDetailView(ModelViewSet): #只需要写这一个,5个接口都有了 queryset= Publish.objects.all() serializer_class=PublishSerializers #不过路由需要传参 url(r'^books/$', views.Book.as_view({'get': 'list', 'post': 'create'})), url(r'^books/(?P<pk>d+)/$',views.Book.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
这种情况不建议使用,一般自己写类,继承魔法类,自己在类中实现功能
#1、ModelViewSet class ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, #前四个已经了解 GenericViewSet): #重点读这个源码 2、#来到GenericViewSet class GenericViewSet(ViewSetMixin, generics.GenericAPIView): pass #源码的pass #它继承了ViewSetMixin #3、来看ViewSetMixin #url(r'^books/$', views.Book.as_view({'get': 'list', 'post': 'create'})), #url(r'^books/(?P<pk>d+)/$',views.Book.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})), class ViewSetMixin(object): #路由的参数给actions def as_view(cls, actions=None, **initkwargs): def view(request, *args, **kwargs): #重写了view方法 #{'get': 'list', 'post': 'create'} #如果method=get ,action = list for method, action in actions.items(): #解压取值 #handler 就是list的内存地址 handler = getattr(self, action) #把list的内存地址,赋值给了get, setattr(self, method, handler) 那么如果是{'get': 'retrieve'},,直接把retrieve赋值给get
#可以实现在一个类中,路由地址不一样 from rest_framework.viewsets import ViewSetMixin #注意前后顺序,ViewSetMixin一定放在前边,为了执行它的as_view方法 class TestAll(ViewSetMixin,APIView): def text1(self,request): return HttpResponse('text1') def text2(self,request): return HttpResponse('text2') def text3(self,request): return HttpResponse('text3') def text4(self,request): return HttpResponse('text4') ------------------------------------------------ urls url(r'^text1/$', views.TestAll.as_view({'get': 'tet1'})), url(r'^text1/$', views.TestAll.as_view({'get': 'tet2'})), url(r'^text1/$', views.TestAll.as_view({'get': 'tet3'})), url(r'^text1/$', views.TestAll.as_view({'get': 'tet4'})),