REST-framework快速构建API--四部曲
作者:@skyflask
转载本文请注明出处:https://www.cnblogs.com/skyflask/p/10398679.html
目录
一、使用原生APIView
二、使用mixins
三、使用generics
四、使用viewsets
代码目录结构:
一、使用原生APIView
使用rest-framework原生的APIView实现过程:
以url(r'^books/$', views.BookView.as_view(),name="books")为例进行流程分析,
- 1、views.BookView.as_view()==>APIView的as_view方法==>父类【View】的as_view方法
- 2、View的as_view方法实际上是返回了View下的view方法
- 3、view实际上是执行了dispatch方法
- 4、dispatch执行过程是去找对应的get/post/put/delete/patch方法
代码实现如下:
urls文件
PublishView用于处理publishes的get和post,获取多个资源的情况
PublishDetailView用于处理publishes/1/的get、put、delete,获取单个资源的情况
1 2 | url(r '^publishes/$' , views.PublishView.as_view(),name= "publish" ), url(r '^publishes/(?P<pk>\d+)/$' , views.PublishDetailView.as_view(),name= "detailpublish" ), |
views文件
使用rest-framework原生的APIView,按照上面说的流程,最后进入dispatch方法,所以只需要我们自己重写get/post/put/delete等方法即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | from rest_framework.views import APIView # Publish表 class PublishView(APIView): def get (self,request): publish_list = Publish.objects.all() ps = PublishModelSerializers(publish_list, many=True) return Response(ps.data) def post(self,request): # post请求的数据 ps = PublishModelSerializers(data=request.data) if ps.is_valid(): print(ps.validated_data) ps.save() # create方法 return Response(ps.data) else : return Response(ps.errors) class PublishDetailView(APIView): def get (self, request, pk): publish = Publish.objects.filter(pk=pk).first() ps = PublishModelSerializers(publish) return Response(ps.data) def put(self, request, pk): publish = Publish.objects.filter(pk=pk).first() ps = PublishModelSerializers(publish, data=request.data) if ps.is_valid(): ps.save() return Response(ps.data) else : return Response(ps.errors) def delete(self, request, pk): Publish.objects.filter(pk=pk).delete() return Response() |
serializer文件
通过ModelSerializer类,指定model和fields进行序列化操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 | from rest_framework import serializers from app01.models import * # 为queryset,model对象做序列化 class PublishSerializers(serializers.Serializer): name = serializers.CharField() email = serializers.CharField() class PublishModelSerializers(serializers.ModelSerializer): class Meta: model=Publish fields= "__all__" |
原生APIView的缺点
针对每个model,需要自己写API的各种方法,代码重复程度很高。
进一步解决办法:使用mixins
二、使用mixins
mixins在上一步的基础上进行了进一步的封装,也就是把多资源情况下的GET/POST以及单资源情况下的GET/POST/PUT/DELETE进行了再次封装,只要我们指定集成的类,然后重写对应的方法即可,urls也不用变更。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | from rest_framework import mixins from rest_framework import generics class AuthorView(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,*args, **kwargs): return self.retrieve(request,*args, **kwargs) def delete(self,request,*args, **kwargs): return self.destroy(request,*args, **kwargs) def put(self,request,*args, **kwargs): return self.retrieve(request,*args, **kwargs) |
使用mixins还是有代码重复的缺点,每个model表都需要重写这一堆方法和类。
三、使用generics
使用generics可以很好的避免上面的问题,他直接包含了多资源和单资源情况下的所有方法,而不需要重写get、post、put、delete方法,甚至还包括patch方法。
1 2 3 4 5 6 7 8 9 10 11 | from rest_framework import mixins from rest_framework import generics class AuthorView(generics.ListCreateAPIView): queryset=Author.objects.all() serializer_class =AuthorModelSerializers class AuthorDetailView(generics.RetrieveUpdateDestroyAPIView): queryset = Author.objects.all() serializer_class = AuthorModelSerializers |
但是这里还有一个缺点,就是单资源和多资源的视图函数以及url都是两份,是不是可以进行一步封装呢?
四、使用viewsets
使用viewsets可以通过在as_view中传参进一步简化操作。
在as_view中传入{动作:方法}的字典给action参数,然后通过getattr和setattr方法进行参数解析,然后通过dispatch中执行对应的方法。
urls文件
1 2 3 4 5 6 7 | url(r '^books/$' , views.BookViewSet.as_view({ "get" : "list" , "post" : "create" }),name= "book_list" ), url(r '^books/(?P<pk>\d+)$' , views.BookViewSet.as_view({ 'get' : 'retrieve' , 'put' : 'update' , 'patch' : 'partial_update' , 'delete' : 'destroy' }),name= "book_detail" ), |
views文件
1 2 3 | class BookViewSet(viewsets.ModelViewSet): queryset = Book.objects.all() serializer_class = BookSerializers |
这就是最终版本,对于一个model表,url两个,一个ModelViewSet类就可以轻易的实现一个API!
进一步简化
我们可以看到urls里面看上去是不是很乱的样子,其实,rest-framework也已经解决了这个脏乱差的问题,通过使用routers!
urls文件修改
以books为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from django.conf.urls import url,include from django.contrib import admin from rest_framework import routers from app01 import views #router实例化,并将Viewset进行注册 router = routers.DefaultRouter() router.register(r 'books' ,views.BookViewSet) #路由控制 urlpatterns = [ url(r '^admin/' , admin.site.urls), url(r '^publishes/$' , views.PublishView.as_view(),name= "publish" ), # View:view(request)=====APIView:dispatch() url(r '^publishes/(?P<pk>\d+)/$' , views.PublishDetailView.as_view(),name= "detailpublish" ), # View:view(request)=====APIView:dispatch() url(r '' ,include(router.urls)), ] |
其他Viewset需要实例化,同样的操作即可,urls的最终结果为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | from django.conf.urls import url,include from django.contrib import admin from rest_framework import routers from app01 import views #router实例化,并将Viewset进行注册 router = routers.DefaultRouter() router.register(r 'books' ,views.BookViewSet) router.register(r 'books' ,views.PublishViewSet) #路由控制 urlpatterns = [ url(r '^admin/' , admin.site.urls), url(r '' ,include(router.urls)), ] |
是不是很简洁?
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」