微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

DRF 视图和路由

Django Rest Feamework 视图和路由

DRF的视图

APIView

我们django中写CBV的时候继承的是View,rest_framework继承的是APIView,那么他们两个有什么不同呢

urlpatterns =\d+)$

我们可以看到,不管是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的一些区别~~当然还有~~后面我们还会说~~

我们写的视图可能对多个表进行增删改查,就导致我们的视图特别多重复的代码~~

那么我们尝试着来进行封装一下~~

第一次封装

display: none;" onclick="cnblogs_code_hide('0592368f-a853-4074-9cf6-6b48c02e903c',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
</span><span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; get(self,request): query_set </span>=<span style="color: #000000;"&gt; Book.objects.all() book_ser </span>= BookSerializer(query_set,many=<span style="color: #000000;"&gt;True) </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; Response(book_ser.data) </span><span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; post(self,request): query_set </span>=<span style="color: #000000;"&gt; request.data book_ser </span>= BookSerializer(data=<span style="color: #000000;"&gt;query_set) </span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; book_ser.is_valid(): book_ser.save() </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; Response(book_ser.validated_data) </span><span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt;: </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; Response(book_ser.errors)

<span style="color: #0000ff;">class<span style="color: #000000;"> BookEditView(APIView):

</span><span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; get(self,request,id):
    query_set </span>= Book.objects.filter(id=<span style="color: #000000;"&gt;id).f<a href="/tag/irs/" target="_blank" class="keywords">irs</a>t()
    book_ser </span>=<span style="color: #000000;"&gt; BookSerializer(query_set)
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; Response(book_ser.data)

</span><span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; patch(self,id):
    query_set </span>= Book.objects.filter(id=<span style="color: #000000;"&gt;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;"&gt;True)
    </span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; book_ser.is_valid():
        book_ser.save()
        </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; Response(book_ser.validated_data)
    </span><span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt;:
        </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; Response(book_ser.errors)

</span><span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; delete(self,id):
    query_set </span>= Book.objects.filter(id=<span style="color: #000000;"&gt;id).f<a href="/tag/irs/" target="_blank" class="keywords">irs</a>t()
    </span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; query_set:
        query_set.delete()
        </span><span style="color: #0000ff;"&gt;return</span> Response(<span style="color: #800000;"&gt;""</span><span style="color: #000000;"&gt;)
    </span><span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt;:
        </span><span style="color: #0000ff;"&gt;return</span> Response(<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;<a href="/tag/shanchu/" target="_blank" class="keywords">删除</a>的书籍不存在</span><span style="color: #800000;"&gt;"</span>)</pre>
display: none;" onclick="cnblogs_code_hide('1bd8e672-4a91-4901-b764-36c8bce19656',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
==</span><span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; get_queryset(self): </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; self.queryset.all() </span><span style="color: #0000ff;"&gt;def</span> get_serializer(self,*args,**<span style="color: #000000;"&gt;<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>): </span><span style="color: #0000ff;"&gt;return</span> self.serializer_class(*args,**<span style="color: #000000;"&gt;<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;"&gt;def</span> get(self,**<span style="color: #000000;"&gt;<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>):
    </span><span style="color: #0000ff;"&gt;return</span> self.list(request,**<span style="color: #000000;"&gt;<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>)

</span><span style="color: #0000ff;"&gt;def</span> post(self,**<span style="color: #000000;"&gt;<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>):
    </span><span style="color: #0000ff;"&gt;return</span> self.create(request,**<span style="color: #000000;"&gt;<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;"&gt;def</span> get(self,**<span style="color: #000000;"&gt;<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>):
    </span><span style="color: #0000ff;"&gt;return</span> self.retrieve(request,**<span style="color: #000000;"&gt;<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>)

</span><span style="color: #0000ff;"&gt;def</span> patch(self,**<span style="color: #000000;"&gt;<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>):
    </span><span style="color: #0000ff;"&gt;return</span> self.update(request,**<span style="color: #000000;"&gt;<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>)

</span><span style="color: #0000ff;"&gt;def</span> destroy(self,**<span style="color: #000000;"&gt;<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>):
    </span><span style="color: #0000ff;"&gt;return</span> self.delete(request,**<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>)</pre>

我们封装的GenericAPIView,包括封装每个方法的类,其实框架都帮我们封装好了

我们可以直接继承这些类~~来实现上面的视图~~可是还有没有更简单的方法呢~我们再次封装一下

第二次封装

display: none;" onclick="cnblogs_code_hide('1b6103fe-d335-4b12-a347-1fc17345247c',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">

<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;"&gt;def</span> get(self,**<span style="color: #000000;"&gt;<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;"&gt;def</span> get(self,**<span style="color: #000000;"&gt;<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>)

</span><span style="color: #0000ff;"&gt;def</span> delete(self,**<a href="/tag/kwargs/" target="_blank" class="keywords">kwargs</a>)</pre>

这次我们只是让继承变的简单了一点而已,好像并没有什么大的进步~~

我们可不可以把这两个视图合并成一个视图呢~~~框架给我们提供了一个路由传参的方法~~

我们看下ViewSetMixin

actions这个认参数其实就是我们路由可以进行传参了~~~

下面这个循环~可以看出~我们要传的参数是一个字段~key应该是我们的请求方式,value应该对应我们处理的方法~

这样我们每个视图就不用在写函数了~因为已经和内部实现的函数相对应了~

第三次封装

display: none;" onclick="cnblogs_code_hide('84e40e4d-20ed-4814-be31-d7d8580f57bf',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
urlpatterns = \d+)$', url(r,BookView.as_view({: ,: \d+)$,BookView.as_view({: ,: ,:
display: none;" onclick="cnblogs_code_hide('14387bee-4d20-45ab-a360-0347f8420bfa',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
rest_framework.viewsets <span style="color: #008000;">#<span style="color: #008000;"> class BookView(ViewSetMixin,ListCreateAPIView,RetrieveUpdateDestroyAPIView):<span style="color: #008000;">

<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,自定义路由

display: none;" onclick="cnblogs_code_hide('7501b7a7-f92a-4128-bc2c-a72f96f528fc',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
django.conf.urls web.views urlpatterns =<span style="color: #000000;"> [
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[a-z0-9]+)$<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: #000000;">,url(r<span style="color: #800000;">'<span style="color: #800000;">^test/(?P[^/.]+).(?P[a-z0-9]+)$<span style="color: #800000;">'<span style="color: #000000;">,s11_render.TestView.as_view())
]

display: none;" onclick="cnblogs_code_hide('be3554a1-2a7e-4b44-bc54-ac0b3283848f',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
rest_framework.views rest_framework.response .. <span style="color: #0000ff;">class<span style="color: #000000;"> TestView(APIView):
<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,半自动路由

display: none;" onclick="cnblogs_code_hide('32f6b9ce-d31a-4666-abe7-9ef6ea93a5e6',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
django.conf.urls web.views urlpatterns =<span style="color: #000000;"> [
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\d+)/$<span style="color: #800000;">'<span style="color: #000000;">,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;">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;">})),]

display: none;" onclick="cnblogs_code_hide('50c52037-7cdb-4dd5-803f-2f8145e4895d',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
rest_framework.viewsets rest_framework .. <span style="color: #0000ff;">class<span style="color: #000000;"> UserSerializer(serializers.ModelSerializer):
<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,全自动路由

display: none;" onclick="cnblogs_code_hide('74324476-1a48-4c53-8eed-a44f6d74095e',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
django.conf.urls rest_framework web.views router =<span style="color: #000000;"> routers.DefaultRouter()
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)),]

display: none;" onclick="cnblogs_code_hide('ed116831-6e84-454f-9311-6e368df5e1b5',event)" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt="">
rest_framework.viewsets rest_framework .. <span style="color: #0000ff;">class<span style="color: #000000;"> UserSerializer(serializers.ModelSerializer):
<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] 举报,一经查实,本站将立刻删除。

相关推荐