路由
url(r'^publish/$', views.PublishView.as_view()), url(r'^publish/(?P<pk>d+)/$', views.PublishDetailView.as_view()),
基本视图
from rest_framework.response import Response from rest_framework import serializers from app01 import models from rest_framework.views import APIView # Create your views here. class PublishSerializers(serializers.ModelSerializer): class Meta: model=models.Publish fields='__all__' #基本视图 class PublishView(APIView): def get(self, request): publish_list = models.Publish.objects.all() bs = PublishSerializers(publish_list, many=True) # 序列化数据 return Response(bs.data) def post(self, request): # 添加一条数据 print(request.data) bs=PublishSerializers(data=request.data) if bs.is_valid(): bs.save() # 生成记录 return Response(bs.data) else: return Response(bs.errors) class PublishDetailView(APIView): def get(self,request,pk): publish_obj=models.Publish.objects.filter(pk=pk).first() bs=PublishSerializers(publish_obj,many=False) return Response(bs.data) def put(self,request,pk): publish_obj = models.Publish.objects.filter(pk=pk).first() bs=PublishSerializers(data=request.data,instance=publish_obj) if bs.is_valid(): bs.save() # update return Response(bs.data) else: return Response(bs.errors) def delete(self,request,pk): models.Publish.objects.filter(pk=pk).delete() return Response("")
minins类和generice类编写视图
from app01 import models from rest_framework import serializers # Create your views here. class PublishSerializers(serializers.ModelSerializer): class Meta: model = models.Publish fields ='__all__'
#基于mixins来封装视图 from rest_framework.mixins import CreateModelMixin,ListModelMixin,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin from rest_framework.generics import GenericAPIView class PublishView(CreateModelMixin,ListModelMixin,GenericAPIView): queryset = models.Publish.objects.all() serializer_class = PublishSerializers def post(self,request,*args,**kwargs): return self.create(request,*args,**kwargs) def get(self,request,*args,**kwargs): return self.list(request,*args,**kwargs) class PublishDetailView(RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin,GenericAPIView): queryset = models.Publish.objects.all() serializer_class = PublishSerializers 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)
源码分析
分析这两个到底是啥东西?
serializer_class
这两个东西是在GenericAPIView里面
继续往下看,,然后发现create方法里面用到了这个方法
这里get_serializer是序列化的类
本质就是调了再点进去看看直接return了serializer_class,然而这里是None,所以我们需要在自己写的类里面把这两个东西配置好。然后就把PublishSerializers传过去,
querset
然后看一下querset,querset是list的时候用的这里不能直接ctrl点进去看,自己没有,ListModeMixin也没有,就应该在GenericAPIView里面,
获取此视图的项列表。这必须是一个可迭代的,并且可能是一个queryset。一般情况下都会加.all,免得耗费资源
第二种写法
from rest_framework.generics import CreateAPIView,ListCreateAPIView,DestroyAPIView,RetrieveUpdateDestroyAPIView class PublishView(ListCreateAPIView): queryset = models.Publish.objects.all() serializer_class = PublishSerializers class PublishDetailView(RetrieveUpdateDestroyAPIView): queryset = models.Publish.objects.all() serializer_class = PublishSerializers
源码部分
ListCreateAPIView里面继承了ListModelMixin,CreateModelMixin,GenericAPIView里面封装了get和list方法
RetrieveUpdateDestroyAPIView里面也是一样封装了get,put/patch,delete方法
第三种写法
五个接口写在一个类中
路由
url(r'^publish/$', views.PublishView.as_view({'get':'list','post':'create'})), url(r'^publish/(?P<pk>d+)/$', views.PublishView.as_view({'get':'retrieve','put':'update','delete':'destroy'})),
from rest_framework.viewsets import ModelViewSet class PublishView(ModelViewSet): queryset=models.Publish.objects.all() serializer_class=PublishSerializers
源码部分
继承了五个了方法的类
注意这里的GenericViewSet不是GenericAPIView,来我们点进去看一下
发现里面没有写,这里唯一没见过的就是ViewSetMixin,点进去看一下
这里的意思是
这就是魔法。重写' .as_view() ',使其接受' actions '关键字,该关键字将HTTP方法绑定到资源上的操作。例如,要创建一个将“GET”和“POST”方法绑定到“list”和“create”操作的具体视图……
这里面的as_view跟原来的as_view多了一个actions的参数
路由里面是字典
所以这里的actions就是路由配置的字典
如果继承了ViewSetMixin就必须穿actions参数否则就抛异常
重点来了
这里重写了view方法,这里把收到的字典key和value取出来,
通过反射去里面找list,然后把list的内存地址给了get,这就是为啥执行了get请求执行的是list方法 ,这样一个视图类就可以相应很多方法,只要有映射关系
as_view方法内部执行效果
通过反射的取值跟赋值,完成映射,根据请求方式执行对应的方法(比如:get请求执行list方法,在路由中配置{get:liste})
ViewSetMixin重写了as_view方法
from rest_framework.viewsets import ViewSetMixin from rest_framework.views import APIView # ViewSetMixin 重写了as_view方法 class Test(ViewSetMixin,APIView): def aaa(self,request): return Response()
这里没有继承View和APIView,所以视图类中还要继承APIView,
但是有先后顺序,因为APIView里面也有个as_view,就会先调用这个,所以放在后面
路由配置就要改了 比如
url(r'^aa/$', views.PublishView.as_view({'get': 'aaa'})),
这样get请求来了就走aaa这个方法