今天我们来看看restframework框架的视图组件,这个组件对我们的请求进行了一系列封装,我们对数据的操作都被封装在一个个接口里,使用起来很方便。
一,常见的几种视图组件方式
1,方式一,在Djiango框架中,我们用CBV模式写视图时是这样写的:
from django.views import View
from django.core.serializers import serialize
class Get_ret(View): def get(self,request): ret=models.Book.objects.all() ret=serialize('json',ret) return HttpResponse(ret) def post(self,request): pass
url文件中url路径是这样写的:
url(r'^ret/', views.Get_ret.as_view()), #走View的as_view方法
在之前文章中我们已经了解它们的执行流程了,前端的请求经过View模块根据不同的请求方式做相应的操作,这里我就不多做讲解了。
2,方式二,restframework框架的视图组件,在restframework框架里views里封装了一个APIView方法,里面定义了自己的as_view方法,这个方法调用了父类View的as_view方法,实例化父类的view方法
只不过里面的dispatch()方法是实例化自己的dispatch()方法,里面的功能与父类的基本相同,只不过加了一些逻辑判断,具体的可以看我上一篇博文,里面有详细讲解。这种方式的写法与第一种方式
基本一样:
view视图文件:
from app01.serializes import BookSerialize from rest_framework.response import Response class BookView(APIView): def get(self,request): #查看所有数据请求 book_list = Book.objects.all() #得到所有数据 bs = BookSerialize(book_list,many=True) #调用rest_framework的序列化功能将数据序列化josn格式 return Response(bs.data) #将数据返回 def post(self,request): #创建数据请求 print(request.data) bs = BookSerialize(data=request.data) #将前端发送的数据反序列化 if bs.is_valid(): #serializers.ModelSerializer它既可以序列化数据,也可以对数据做验证 bs.save() #调用数据库创建功能 return Response(bs.data) #将新数据返回给前端 else: return Response(bs.errors)
class BookDataView(APIView):
def get(self,request,pk): #查看某条数据请求
book_obj = Book.objects.filter(pk=pk).first()
bs = BookSerialize(book_obj,many=False) #many参数为False是查看单条数据
return Response(bs.data)
def put(self,request,pk): #更改某条数据请求
book_obj = Book.objects.filter(pk=pk).first()
bs = BookSerialize(data=request.data,instance=book_obj)
if bs.is_valid():
bs.save()
return Response(bs.data)
def delete(self,request,pk): #删除某条数据请求
Book.objects.filter(pk=pk).delete()
return Response('OK')
url文件设计:
url(r'^books/$', views.BookView.as_view()), #book发送查看,创建请求路由 url(r'^books/(?P\d+)/$ ', views.BookDataView.as_view()), #book发送更改,删除请求
3,方式三,在rest_framework模块的mixins里封装了我们经常使用的请求方法,如果只是对一些数据做处理,业务逻辑相同的话我建议使用这种方法,这会减少我们的代码量。
在view视图文件:
from rest_framework.mixins import CreateModelMixin,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin,ListModelMixin from rest_framework import generics from app01.serializes import PublishSerialize class PublishView(ListModelMixin,CreateModelMixin,generics.GenericAPIView): queryset = Publish.objects.all() serializer_class = PublishSerialize def get(self,request): #查看所有的数据请求 return self.list(request) def post(self,request): #创建数据请求 return self.create(request) class PublishDetaView(RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin,generics.GenericAPIView): queryset = Publish.objects.all() serializer_class = PublishSerialize 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文件中:
url(r'^publish/$', views.PublishView.as_view()), url(r'^publish/(?P\d+)/$', views.PublishDetaView.as_view()),
这种方式与APIView方式很相似,只是把一些查看,创建,修改,删除的方法封在一些list,update,destroy...里面,你在相应的请求下调用就可以了,里面会帮你做逻辑处理跟序列化处理,我们查看
源码就可以看出来:
在我看来这种方式还是不够简便,只是减少了一些业务逻辑,但是缺失了一些灵活性,一些请求我们需要经过一些逻辑判断再来处理,所以这种方式显然没办法满足我们的需求。
下面我要讲的是一种更简便的方式,只需要几行代码就能实现。
4,方式四,ModelViewset方法,这个方法里包含了上面所有的请求方法,我们自需要在我们定义的视图类上继承就可以使用。
view视图文件:
from rest_framework.viewsets import ModelViewSet class AuthorDetaView (ModelViewSet): queryset = Author.objects.all() #拿到后端数据 serializer_class = AuthorSerialize
url文件:
url(r'^authors/$', views.AuthorSerialize.as_view({"get":"list","post":"create"})), url(r'^authors/(?P\d+)/$ ', views.AuthorSerialize.as_view({"get":"retrieve","put":"update","delete":"destroy"})) #视图类只需要定义一个
我们看url可以看出,这两条url走的是一个试图类,并且每条url都带有参数,这里as_view方法到底是走的哪个类下的方法呢?通过查看源码跟面向对象的继承类的多继承属性我们最后发现走的是
一个ViewSetMixin类下的as_view方法,并且它接收了actions参数
这给方法最后也是返回的是它下面的view返回值,所有关键是这个view方法里执行了什么操作,我们继续看源码:
我们看源码可以看到,它里面对我们前面的传的字典参数做了一个循环取值,然后通过反射找到一个个对应的方法,最后通过setattr方法重新设值,简单来说就是把get方法设置成list方法,后面得方法也是一样,这样我们就可以把前端的请求方法改成我们的list,updata...方法,最后执行dispatch方法执行后面的逻辑。