视图三部曲
第一种方式:
使用混合(mixins):
serialize.py
class AuthorModelSerializers(serializers.ModelSerializer): class Meta: model = Author fields = "__all__"
urls.py
url(r'authors/$', views.AuthoView.as_view(),name="authors"), url(r'authors/(?P<pk>d+)/$', views.AuthorDetailView.as_view(),name="authordetail")
views.py
from rest_framework import mixins from rest_framework import generics class AuthoView(mixins.ListModelMixin,mixins.CreateModelMixin,generics.GenericAPIView): queryset=Author.objects.all() serializer_class=AuthorModelSerializers 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 AuthorDetailView(mixins.RetrieveModelMixin,mixins.DestroyModelMixin,mixins.UpdateModelMixin,generics.GenericAPIView): queryset=Author.objects.all() serializer_class=AuthorModelSerializers def get(self,request,pk,*args,**kwargs): return self.retrieve(request,pk,*args,**kwargs) def delete(self,request,pk,*args,**kwargs): return self.destroy(request,pk,*args,**kwargs) def put(self,request,pk,*args,**kwargs): return self.update(request,pk,*args,**kwargs)
因为每一个表都进行一次的重复操作会使得代码冗余,所以使用封装好的mixin会稍微简洁一些,
mixin:
ListModelMxin #查看
CreateModelMixin #新建
DestoryModelMixin #删除
RetrieveModelMixin #查看具体一条
UpdateModelMixin #更新
第二种方式:
使用通用的基于类的视图
通过使用mixin类,我们使用更少的代码重写了这些视图,但我们还可以再进一步。REST框架提供了一组已经混合好(mixed-in)的通用视图,我们可以使用它来简化我们的views.py
模块。
#其他不变: from rest_framework import mixins from rest_framework import generics class AuthoView(generics.ListCreateAPIView): queryset=Author.objects.all() serializer_class=AuthorModelSerializers class AuthorDetailView(generics.RetrieveUpdateDestroyAPIView): queryset=Author.objects.all() serializer_class=AuthorModelSerializers
继承关系做了进一步的封装,方法也进行了更加简练的优化,方法全部写进了源码内。
第三种方式:
viewsets.ModelViewSet
views.py
from rest_framework import viewsets class AuthorModelView(viewsets.ModelViewSet): queryset=Author.objects.all() serializer_class=AuthorModelSerializers
urls.py
url(r'authors/$', views.AuthorModelView.as_view({"get":"list","post":"create"}),name="authors"), url(r'authors/(?P<pk>d+)/$', views.AuthorModelView.as_view({"get":"retrieve","put":"update","delete":"destroy"}),name="authordetail"),
2趟线使用同一个类,在urls中的as_view()中加入参数,让不同的请求方式走不同的方法。
这里看源码中遇到的一个薄弱点,这里记录一下:
def foo(action=None,**kwargs): print(action) print(kwargs) foo(**{"d":5}) print("______________") foo({"d":5}) #总结:**字典等同于关键字传参 None {'d': 5} ______________ {'d': 5} {}
这个传参方式需要注意一下。
总结:
从源码中摘出来的部分代码,组成了最后的流程。
流程: (1)url(r'^authors/$', views.AuthorModelView.as_view({"get":"list","post":"create"}),name="author"), (2)url(r'^authors/$', ViewSetMixin.as_view({"get":"list","post":"create"}),name="author"), (3)url(r'^authors/$', ViewSetMixin类下的view), 一旦访问 /authors/: ViewSetMixin def view(): for method, action in actions.items(): # {"get":"list","post":"create"} handler = getattr(self, action) # self.list self.create setattr(self, method, handler) #self.get = self.list self.post=self.post #这里取到了get,post等方法后,赋值给handler,然后通过setattr()
#执行dispatch方法 self.dispatch(request, *args, **kwargs)
APIView类下的self.dispatch #这个dispatch方法是APIView里面的,返回的是response. # 分发 if request.method.lower() in self.http_method_names:
#getattr(self,"get") --->self.list
#getattr(self,"post") --->self.create
handler = getattr(self,request.method.lower()) #这里真正执行的是list,create方法。
#最终执行handler(). response = handler(request, *args, **kwargs) # self.list()
#将response返回。 return response