Django Rest Feamework 视图和路由
DRF的视图
APIView
我们django中写CBV的时候继承的是View,rest_framework继承的是APIView,那么他们两个有什么不同呢
我们可以看到,不管是View还是APIView最开始调用的都是as_view()方法~~那我们走进源码看看~~
我们能看到,APIView继承了View,并且执行了View中的as_view()方法,最后把view返回了,用csrf_exempt()方法包裹后去掉了csrf的认证。
那我们看看View中的as_view()方法做了什么~
502ad9cc2a606590f.png" alt="">
我们看到了~在View中的as_view方法返回了view函数,而view函数执行了self.dispatch()方法~~但是这里的dispatch方法应该是我们APIView中的~~
我们去initialize_request中看下把什么赋值给了request,并且赋值给了self.request,也就是我们在视图中用的request.xxx到底是什么~~
fdb1abee44052648d.png" alt="">
我们看到,这个方法返回的是Request这个类的实例对象~~我们注意我们看下这个Request类中的第一个参数request,是我们走我们django的时候的原来的request~
我们看到了,这个Request类把原来的request赋值给了self._request,也就是说以后_request是我们老的request,新的request是我们这个Request类~~
那我们继承APIView之后请求来的数据都在哪呢~~
我们用了rest_framework框架以后,我们的request是重新封装的Request类~
request.query_params 存放的是我们get请求的参数
request.data 存放的是我们所有的数据,包括post请求的以及put,patch请求~~~
相比原来的django的request,我们现在的request更加精简,清晰了~~~
现在我们知道了APIView和View的一些区别~~当然还有~~后面我们还会说~~
我们写的视图可能对多个表进行增删改查,就导致我们的视图特别多重复的代码~~
那么我们尝试着来进行封装一下~~
第一次封装
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> get(self,request):
query_set </span>=<span style="color: #000000;"> Book.objects.all()
book_ser </span>= BookSerializer(query_set,many=<span style="color: #000000;">True)
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> Response(book_ser.data)
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> post(self,request):
query_set </span>=<span style="color: #000000;"> request.data
book_ser </span>= BookSerializer(data=<span style="color: #000000;">query_set)
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> book_ser.is_valid():
book_ser.save()
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> Response(book_ser.validated_data)
</span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> Response(book_ser.errors)
<span style="color: #0000ff;">class<span style="color: #000000;"> BookEditView(APIView):
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> get(self,request,id):
query_set </span>= Book.objects.filter(id=<span style="color: #000000;">id).f<a href="/tag/irs/" target="_blank" class="keywords">irs</a>t()
book_ser </span>=<span style="color: #000000;"> BookSerializer(query_set)
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> Response(book_ser.data)
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> patch(self,id):
query_set </span>= Book.objects.filter(id=<span style="color: #000000;">id).f<a href="/tag/irs/" target="_blank" class="keywords">irs</a>t()
book_ser </span>= BookSerializer(query_set,data=request.data,partial=<span style="color: #000000;">True)
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> book_ser.is_valid():
book_ser.save()
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> Response(book_ser.validated_data)
</span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> Response(book_ser.errors)
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> delete(self,id):
query_set </span>= Book.objects.filter(id=<span style="color: #000000;">id).f<a href="/tag/irs/" target="_blank" class="keywords">irs</a>t()
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> query_set:
query_set.delete()
</span><span style="color: #0000ff;">return</span> Response(<span style="color: #800000;">""</span><span style="color: #000000;">)
</span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
</span><span style="color: #0000ff;">return</span> Response(<span style="color: #800000;">"</span><span style="color: #800000;"><a href="/tag/shanchu/" target="_blank" class="keywords">删除</a>的书籍不存在</span><span style="color: #800000;">"</span>)</pre>
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> get_queryset(self):
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> self.queryset.all()
</span><span style="color: #0000ff;">def</span> get_serializer(self,*args,**<span style="color: #000000;"><a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>):
</span><span style="color: #0000ff;">return</span> self.serializer_class(*args,**<span style="color: #000000;"><a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>)
<span style="color: #0000ff;">class<span style="color: #000000;"> ListModelMixin(object):<span style="color: #0000ff;">def list(self,**<span style="color: #000000;">kwargs):
queryset =<span style="color: #000000;"> self.get_queryset()
serializer = self.get_serializer(queryset,many=<span style="color: #000000;">True)
<span style="color: #0000ff;">return<span style="color: #000000;"> Response(serializer.data)
<span style="color: #0000ff;">class<span style="color: #000000;"> CreateModelMixin(object):
<span style="color: #0000ff;">def create(self,**<span style="color: #000000;">kwargs):
serializer = self.get_serializer(data=<span style="color: #000000;">request.data)
<span style="color: #0000ff;">if<span style="color: #000000;"> serializer.is_valid():
serializer.save()
<span style="color: #0000ff;">return<span style="color: #000000;"> Response(serializer.validated_data)
<span style="color: #0000ff;">else<span style="color: #000000;">:
<span style="color: #0000ff;">return<span style="color: #000000;"> Response(serializer.errors)
<span style="color: #0000ff;">class<span style="color: #000000;"> RetrieveModelMixin(object):
<span style="color: #0000ff;">def retrieve(self,id,**<span style="color: #000000;">kwargs):
book_obj = self.get_queryset().filter(pk=<span style="color: #000000;">id).first()
book_ser =<span style="color: #000000;"> self.get_serializer(book_obj)
<span style="color: #0000ff;">return<span style="color: #000000;"> Response(book_ser.data)
<span style="color: #0000ff;">class<span style="color: #000000;"> UpdateModelMixin(object):
<span style="color: #0000ff;">def update(self,**<span style="color: #000000;">kwargs):
book_obj = self.get_queryset().filter(pk=<span style="color: #000000;">id).first()
book_ser = self.get_serializer(book_obj,partial=<span style="color: #000000;">True)
<span style="color: #0000ff;">if<span style="color: #000000;"> book_ser.is_valid():
book_ser.save()
<span style="color: #0000ff;">return<span style="color: #000000;"> Response(book_ser.validated_data)
<span style="color: #0000ff;">else<span style="color: #000000;">:
<span style="color: #0000ff;">return<span style="color: #000000;"> Response(book_ser.errors)
<span style="color: #0000ff;">class<span style="color: #000000;"> DestroyModelMixin(object):
<span style="color: #0000ff;">def destroy(self,**<span style="color: #000000;">kwargs):
queryset =<span style="color: #000000;"> self.get_queryset()
<span style="color: #0000ff;">try<span style="color: #000000;">:
queryset.get(pk=<span style="color: #000000;">id).delete()
<span style="color: #0000ff;">return Response(<span style="color: #800000;">""<span style="color: #000000;">)
<span style="color: #0000ff;">except<span style="color: #000000;"> Exception as e:
<span style="color: #0000ff;">return Response(<span style="color: #800000;">"<span style="color: #800000;">信息有误<span style="color: #800000;">"<span style="color: #000000;">)
<span style="color: #008000;">#<span style="color: #008000;"> 我们把公共的部分抽出来 这样不管写多少表的增删改查都变的很简单<span style="color: #008000;">
<span style="color: #008000;"> 这样封装后我们的视图会变成这样
<span style="color: #0000ff;">class<span style="color: #000000;"> BookView(GenericAPIView,ListModelMixin,CreateModelMixin):
queryset =<span style="color: #000000;"> Book.objects.all()
serializer_class =<span style="color: #000000;"> BookSerializer
</span><span style="color: #0000ff;">def</span> get(self,**<span style="color: #000000;"><a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>):
</span><span style="color: #0000ff;">return</span> self.list(request,**<span style="color: #000000;"><a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>)
</span><span style="color: #0000ff;">def</span> post(self,**<span style="color: #000000;"><a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>):
</span><span style="color: #0000ff;">return</span> self.create(request,**<span style="color: #000000;"><a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>)
<span style="color: #0000ff;">class<span style="color: #000000;"> BookEditView(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
queryset =<span style="color: #000000;"> Book.objects.all()
serializer_class =<span style="color: #000000;"> BookSerializer
</span><span style="color: #0000ff;">def</span> get(self,**<span style="color: #000000;"><a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>):
</span><span style="color: #0000ff;">return</span> self.retrieve(request,**<span style="color: #000000;"><a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>)
</span><span style="color: #0000ff;">def</span> patch(self,**<span style="color: #000000;"><a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>):
</span><span style="color: #0000ff;">return</span> self.update(request,**<span style="color: #000000;"><a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>)
</span><span style="color: #0000ff;">def</span> destroy(self,**<span style="color: #000000;"><a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>):
</span><span style="color: #0000ff;">return</span> self.delete(request,**<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>)</pre>
我们封装的GenericAPIView,包括封装每个方法的类,其实框架都帮我们封装好了
我们可以直接继承这些类~~来实现上面的视图~~可是还有没有更简单的方法呢~我们再次封装一下
第二次封装
<span style="color: #0000ff;">class
<span style="color: #000000;"> ListCreateAPIView(GenericAPIView,CreateModelMixin):<span style="color: #0000ff;">pass
<span style="color: #0000ff;">class<span style="color: #000000;"> RetrieveUpdateDestroyAPIView(GenericAPIView,DestroyModelMixin):
<span style="color: #0000ff;">pass
<span style="color: #0000ff;">class<span style="color: #000000;"> BookView(ListCreateAPIView):
queryset =<span style="color: #000000;"> Book.objects.all()
serializer_class =<span style="color: #000000;"> BookSerializer
</span><span style="color: #0000ff;">def</span> get(self,**<span style="color: #000000;"><a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>)
<span style="color: #0000ff;">class<span style="color: #000000;"> BookEditView(RetrieveUpdateDestroyAPIView):
queryset =<span style="color: #000000;"> Book.objects.all()
serializer_class =<span style="color: #000000;"> BookSerializer
</span><span style="color: #0000ff;">def</span> get(self,**<span style="color: #000000;"><a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>)
</span><span style="color: #0000ff;">def</span> delete(self,**<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>)</pre>
这次我们只是让继承变的简单了一点而已,好像并没有什么大的进步~~
我们可不可以把这两个视图合并成一个视图呢~~~框架给我们提供了一个路由传参的方法~~
我们看下ViewSetMixin
actions这个默认参数其实就是我们路由可以进行传参了~~~
下面这个循环~可以看出~我们要传的参数是一个字段~key应该是我们的请求方式,value应该对应我们处理的方法~
这样我们每个视图就不用在写函数了~因为已经和内部实现的函数相对应了~
第三次封装
<span style="color: #008000;"> queryset = Book.objects.all()<span style="color: #008000;">
<span style="color: #008000;"> serializer_class = BookSerializer
<span style="color: #008000;">#<span style="color: #008000;"> 如果我们再定义一个类
<span style="color: #0000ff;">class<span style="color: #000000;"> ModelViewSet(ViewSetMixin,RetrieveUpdateDestroyAPIView):
<span style="color: #0000ff;">pass
<span style="color: #0000ff;">class<span style="color: #000000;"> BookView(ModelViewSet):
queryset =<span style="color: #000000;"> Book.objects.all()
serializer_class = BookSerializer
我们现在的视图就只要写两行就可以了~~~
其实我们写的所有的视图~框架都帮我们封装好了~
注意一点~~用框架封装的视图~我们url上的那个关键字参数要用pk~~系统默认的~~
奉献一张图来看下我们的继承顺序~~~
DRF的路由
1,自定义路由
url(r<span style="color: #800000;">'<span style="color: #800000;">^test/$<span style="color: #800000;">'<span style="color: #000000;">,s11_render.TestView.as_view()),url(r<span style="color: #800000;">'<span style="color: #800000;">^test.(?P
]
<span style="color: #0000ff;">def get(self,**<span style="color: #000000;">kwargs):
<span style="color: #0000ff;">print<span style="color: #000000;">(kwargs)
<span style="color: #0000ff;">print<span style="color: #000000;">(self.renderer_classes)
<span style="color: #0000ff;">return Response(<span style="color: #800000;">'<span style="color: #800000;">...<span style="color: #800000;">')
2,半自动路由
url(r<span style="color: #800000;">'<span style="color: #800000;">^test/$<span style="color: #800000;">',s10_generic.UserViewSet.as_view({<span style="color: #800000;">'<span style="color: #800000;">get<span style="color: #800000;">': <span style="color: #800000;">'<span style="color: #800000;">list<span style="color: #800000;">',<span style="color: #800000;">'<span style="color: #800000;">post<span style="color: #800000;">': <span style="color: #800000;">'<span style="color: #800000;">create<span style="color: #800000;">'<span style="color: #000000;">})),url(r<span style="color: #800000;">'<span style="color: #800000;">^test/(?P
{<span style="color: #800000;">'<span style="color: #800000;">get<span style="color: #800000;">': <span style="color: #800000;">'<span style="color: #800000;">retrieve<span style="color: #800000;">',<span style="color: #800000;">'<span style="color: #800000;">put<span style="color: #800000;">': <span style="color: #800000;">'<span style="color: #800000;">update<span style="color: #800000;">',<span style="color: #800000;">'<span style="color: #800000;">patch<span style="color: #800000;">': <span style="color: #800000;">'<span style="color: #800000;">partial_update<span style="color: #800000;">',<span style="color: #800000;">'<span style="color: #800000;">delete<span style="color: #800000;">': <span style="color: #800000;">'<span style="color: #800000;">destroy<span style="color: #800000;">'<span style="color: #000000;">})),]
<span style="color: #0000ff;">class<span style="color: #000000;"> Meta:
model =<span style="color: #000000;"> models.UserInfo
fields = <span style="color: #800000;">"<span style="color: #800000;">all<span style="color: #800000;">"
<span style="color: #0000ff;">class<span style="color: #000000;"> UserViewSet(ModelViewSet):
queryset =<span style="color: #000000;"> models.UserInfo.objects.all()
serializer_class = UserSerializer
3,全自动路由
router.register(r<span style="color: #800000;">'<span style="color: #800000;">users<span style="color: #800000;">'<span style="color: #000000;">,s10_generic.UserViewSet)
urlpatterns
=<span style="color: #000000;"> [url(r<span style="color: #800000;">'<span style="color: #800000;">^<span style="color: #800000;">'<span style="color: #000000;">,include(router.urls)),]
<span style="color: #0000ff;">class<span style="color: #000000;"> Meta:
model =<span style="color: #000000;"> models.UserInfo
fields = <span style="color: #800000;">"<span style="color: #800000;">all<span style="color: #800000;">"
<span style="color: #0000ff;">class<span style="color: #000000;"> UserViewSet(ModelViewSet):
queryset =<span style="color: #000000;"> models.UserInfo.objects.all()
serializer_class = UserSerializer
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。