当前位置: 首页 > 后端技术 > Python

使用DRF时,选择router.register还是urlpatterns路径???

时间:2023-03-26 17:24:37 Python

前言Django开发者转DjangoRESTframework开发者后,你会发现在Django原有urlpatterns路径的基础上多了一个router.register。本来以为Django部分会用urlpatterns路径,DRF部分会用router。.register,但是当我看DjangoRESTframework官方文档(教程三:基于类的视图-英文文档|教程三:基于类的视图-中文文档)时,我发现事情并没有那么简单。传统的内容方式是结论先行。当我们开发的API是继承APIView的时候,那么使用传统的DjangoCBV调用as_view方法在urlpatterns路径中注册路由,就像官方文档中django的例子一样。conf.urlsimporturlfromrest_framework.urlpatternsimportformat_suffix_patternsfromsnippetsimportviewsurlpatterns=[url(r'^snippets/$',views.SnippetList.as_view()),url(r'^snippets/(?P[0-9]+)/$',views.SnippetDetail.as_view()),]urlpatterns=format_suffix_patterns(urlpatterns)SnippetDetail定义如下:classSnippetDetail(APIView):"""检索、更新或删除片段实例。"""defget_object(self,pk):try:returnSnippet.objects.get(pk=pk)除了Snippet.DoesNotExist:raiseHttp404defget(self,request,pk,format=None):snippet=self.get_object(pk)serializer=SnippetSerializer(snippet)返回Response(serializer.data)defput(self,request,pk,format=None):snippet=self.get_object(pk)serializer=SnippetSerializer(snippet,data=request.data)如果serializer.is_valid():serializer.save()returnResponse(serializer.data)returnResponse(serializer.errors,status=status.HTTP_400_BAD_REQUEST)defdelete(self,request,pk,format=None):snippet=self.get_object(pk)snippet.delete()returnResponse(status=status.HTTP_204_NO_CONTENT)继承DjangoRESTframework独有的ViewSet的新方法是用router.register注册路由。继承自ModelViewSet或GenericViewSet等,用ViewSet作为后缀计算。具体可以参考DjangoRESTframework官方文档(教程六:ViewSets&Routers-英文文档|教程六:ViewSets&Routers-中文文档)从django.urls导入路径中提取关键代码,includefromrest_framework.routersimportDefaultRouterfromsnippetsimportviews#创建一个路由器并用它注册我们的viewsetsrouter.urlpatterns=[path('',include(router.urls)),]其中SnippetViewSet定义如下,可以看到SnippetViewSet继承自ModelViewSetfromrest_framework.decoratorsimportactionfromrest_framework.responseimportResponsefromrest_frameworkimportpermissionsSectionppclassviewSetni_frameset(viewsets.ModelViewSet):"""此视图集自动提供`list`、`create`、`retrieve`、`update`和`destroy`操作。此外,我们还提供额外的“突出显示”操作。“”“问yset=Snippet.objects.all()serializer_class=SnippetSerializerpermission_classes=[permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly]@action(detail=True,renderer_classes=[renderers.StaticHTMLRenderer])defhighlight(self,request,*args,)**k:snippet=self.get_object()returnResponse(snippet.highlighted)defperform_create(self,serializer):serializer.save(owner=self.request.user)这两个方法的关系Django的urlpatterns路径和DjangoRESTframeworkTherouter.register不是对立关系,没必要二选一。DRF方法的本质是对Django方法的封装。至于为什么这样封装,是为了更好的组织API。我们也可以在继承自ViewSet的类中使用传统的方法as_view方法,在申诉文档中有详细的回答,大致意思是显式写as_view方法的action参数,是字典类型,申明方法之间的关系,比如asget,post,patch和特定函数的映射关系fromsnippets.viewsimportSnippetViewSet,UserViewSet,api_rootfromrest_frameworkimportrendererssnippet_list=SnippetViewSet.as_view({'get':'list','post':'create'})snippet_detail=SnippetViewSet.as_view({'get':'retrieve','put':'update','patch':'partial_update','delete':'destroy'})snippet_highlight=SnippetViewSet.as_view({'get':'highlight'},renderer_classes=[renderers.StaticHTMLRenderer])user_list=UserViewSet.as_view({'get':'list'})user_detail=UserViewSet.as_view({'get':'retrieve'})