drf : 通用视图类和(GenericAPIView)5个视图扩展类,九个视图子类,视图集。
视图
REST framework 提供了众多的通用视图基类与扩展类,以简化视图的编写。
APIView
rest_framework.views.APIView
APIView是REST framework提供的所有视图的基类,继承自Django的View父类。
GenericAPIView使用[通用视图类]
继承自APIVIew,主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持。通常在使用时,可搭配一个或多个Mixin扩展类。
点击第一层查看代码
class BookView(APIView): renderer_classes = [JSONRenderer] # 创建数据反序列化 def post(self, request): ser = BookSerializers(data=request.data) if ser.is_valid(): ser.save() return Response(ser.data) # 读取序列化 def get(self, request): book_list = Books.objects.all() # many=True 代表序列化多条数据 ser = BookSerializers(instance=book_list, many=True) response = {'code': 100, 'msg': '查询成功', 'result': ser.data} return Response(response, status=status.HTTP_202_ACCEPTED, headers={'name': 'junjie'}) # 查询单条 class BookDetailView(APIView): def get(self, request, pk): book = Books.objects.filter(pk=pk).first() ser = BookSerializers(instance=book) return Response(ser.data) def delete(self, request, pk): Books.objects.filter(pk=pk).delete() return Response() # 修改 def put(self, request, pk): book = Books.objects.filter(pk=pk).first() ser = BookSerializers(instance=book, data=request.data) if ser.is_valid(): ser.save() return Response(ser.data)
GenericAPIView[通用视图类]的方法属性以及方法,第二层的演变。
* 属性
* serializer_class指明视图使用的序列化器
* 方法
* get_serializer_class(self)
现在来想继承GenericAPIView来写视图函数改如何写?先查看GenericAPIView类定义了什么属性和方法。
图书的五个接口,第二层,精简模型类和序列化类
from .models import Books, Publish from rest_framework.generics import GenericAPIView from .serizlizer import BookSerializers, PublishSerializers from rest_framework.response import Response class BookAPIView(GenericAPIView): queryset = Books.objects.all() serializer_class = BookSerializers def get(self, request): book_list = self.get_queryset() ser = self.get_serializer(instance=book_list, many=True) return Response(ser.data) def post(self, request): ser = self.get_serializer(data=request.data) if ser.is_valid(): ser.save() return Response(ser.data) class BookDetailView(GenericAPIView): queryset = Books.objects.all() serializer_class = BookSerializers def get(self, request, pk): book_list = self.get_object() ser = self.get_serializer(instance=book_list) return Response(ser.data) def put(self, request, pk): book_obj = self.get_object() # 得到序列化类对象,传入单条对象和要修改的数据字段 ser = self.get_serializer(instance=book_obj, data=request.data) if ser.is_valid(): ser.save() return Response(ser.data) def delete(self, request, pk): book = self.get_object() book.delete() return Response()
如果想要再写一个视图类只需要继承GenericAPIView修改queryset和serializer_class即可,那么有没有别的方法可以节省代码?
使用GenericAPIView+5个视图扩展类
from rest_framework.mixins import CreateModelMixin, # 创建单个 ListModelMixin, # 查询所有 DestroyModelMixin, # 删除单个 碟嘶踹 UpdateModelMixin, # 新建单个 RetrieveModelMixin # 查询单个 瑞吹雾
代码如下:
from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin, \ ListModelMixin from rest_framework.generics import GenericAPIView from .models import Books, Publish from .serizlizer import BookSerializers, PublishSerializers class BookAPIView(GenericAPIView, # 创建数据 CreateModelMixin, # 查看所有 ListModelMixin): queryset = Books.objects.all() serializer_class = BookSerializers def get(self, request): print(request) return self.list(request) def post(self, request): return self.create(request) class BookDetailView(GenericAPIView, UpdateModelMixin, # 修改单条数据 DestroyModelMixin, # 删除单条 RetrieveModelMixin): # 查询单条 queryset = Books.objects.all() serializer_class = BookSerializers def get(self, request, pk): print(request) return self.retrieve(request, pk) def delete(self, request, pk): print(request) return self.destroy(request, pk) def put(self, request, pk): return self.update(request, pk)
为什么叫视图扩展类:因为他不是视图类,视图类必须是继承View/APIView。
还有没有办法再精简代码?
GenericAPIView的视图子类,第三层
1)CreateAPIView
提供 post 方法
继承自: GenericAPIView、CreateModelMixin
2)ListAPIView
提供 get 方法
继承自:GenericAPIView、ListModelMixin
3)RetrieveAPIView
提供 get 方法
继承自: GenericAPIView、RetrieveModelMixin
4)DestoryAPIView
提供 delete 方法
继承自:GenericAPIView、DestoryModelMixin
5)UpdateAPIView
提供 put 和 patch 方法
继承自:GenericAPIView、UpdateModelMixin
以及:
RetrieveAPIView, ListCreateAPIView, RetrieveUpdateDestroyAPIView, RetrieveUpdateAPIView, RetrieveDestroyAPIView
from rest_framework.generics import CreateAPIView, UpdateAPIView, DestroyAPIView, ListAPIView, RetrieveAPIView, \ ListCreateAPIView, RetrieveUpdateDestroyAPIView, RetrieveUpdateAPIView, RetrieveDestroyAPIView class BookAPIView(ListCreateAPIView): queryset = Books.objects.all() serializer_class = BookSerializers class BookDetailAPIView(RetrieveUpdateDestroyAPIView): queryset = Books.objects.all() serializer_class = BookSerializers
总结:
#两个基类 APIView GenericAPIView:有关数据库操作,queryset 和serializer_class #5个视图扩展类(rest_framework.mixins) CreateModelMixin:create方法创建一条 DestroyModelMixin:destory方法删除一条 ListModelMixin:list方法获取所有 RetrieveModelMixin:retrieve获取一条 UpdateModelMixin:update修改一条 #9个子类视图(rest_framework.generics) CreateAPIView:继承CreateModelMixin,GenericAPIView,有post方法,新增数据 DestroyAPIView:继承DestroyModelMixin,GenericAPIView,有delete方法,删除数据 ListAPIView:继承ListModelMixin,GenericAPIView,有get方法获取所有 UpdateAPIView:继承UpdateModelMixin,GenericAPIView,有put和patch方法,修改数据 RetrieveAPIView:继承RetrieveModelMixin,GenericAPIView,有get方法,获取一条 ListCreateAPIView:继承ListModelMixin,CreateModelMixin,GenericAPIView,有get获取所有,post方法新增 RetrieveDestroyAPIView:继承RetrieveModelMixin,DestroyModelMixin,GenericAPIView,有get方法获取一条,delete方法删除 RetrieveUpdateAPIView:继承RetrieveModelMixin,UpdateModelMixin,GenericAPIView,有get获取一条,put,patch修改 RetrieveUpdateDestroyAPIView:继承RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,GenericAPIView,有get获取一条,put,patch修改,delete删除
第五层,直接写五个接口最终演示,自动生成路由。
from rest_framework.viewsets import ModelViewSet # ModelViewSet继承了5个视图扩展类,GenericViewSet 和 ViewSetMixin class BookAPIView(ModelViewSet): queryset = Books.objects.all() serializer_class = BookSerializers
继承五个视图扩展类的作用为用了五个接口方法。
GenericViewSet是什么?
class GenericViewSet(ViewSetMixin, generics.GenericAPIView): """ The GenericViewSet class does not provide any actions by default, but does include the base set of generic view behavior, such as the `get_object` and `get_queryset` methods. """ pass """ 已知:generics.GenericAPIView 中有View和APIView,以及四个方法 def get_queryset(self): def get_object(self): def get_serializer(self, *args, **kwargs): def get_serializer_class(self): """
ViewSetMixin
class ViewSetMixin: @classonlymethod def as_view(cls, actions=None, **initkwargs): cls.name = None cls.description = None cls.suffix = None cls.detail = None cls.basename = None # 注释: """ 此处与url相对应,actions是什么? path('books/', views.BookAPIView.as_view({'get':'list','post':'create'})), actions = {'get':'list','post':'create'} 如果没有写则报异常。 """ if not actions: raise TypeError("The `actions` argument must be provided when " "calling `.as_view()` on a ViewSet. For example " "`.as_view({'get': 'list'})`") # 注释: """ 字典.items()是将K,V拆出,此时method=K,action=V 以{'get':'list','post':'create'}举例。 get = method,list = action """ for method, action in actions.items(): # 注释: """ 此时的self为视图类对象BookAPIView action是上述所讲的url,as_view的第一个参数。 getattr反射,此时视图类对象中没有list,到父类ModelViewSet --> mixins.ListModelMixin --> def list(self, request, *args, **kwargs): handler 便是反射出来的list setattr设置值,将list映射成get,视图中的get方法实质上是list方法。 客户端发送get请求就能找到list 这里主要用作区分用户是查询单条还是查询所有 """ handler = getattr(self, action) setattr(self, method, handler) self.request = request self.args = args self.kwargs = kwargs # And continue as usual return self.dispatch(request, *args, **kwargs) # take name and docstring from class update_wrapper(view, cls, updated=()) # and possible attributes set by decorators # like csrf_exempt from dispatch update_wrapper(view, cls.dispatch, assigned=()) # We need to set these on the view function, so that breadcrumb # generation can pick out these bits of information from a # resolved URL. view.cls = cls view.initkwargs = initkwargs view.actions = actions return csrf_exempt(view)
第五层
导入模块
from rest_framework.viewsets import ModelViewSet
直接写五个接口最终演示,自动生成路由。
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet, GenericViewSet, ViewSet # 直接写五个接口,一定要继承(ViewSetMixin),才能自动生成路由 # class BookAPIView(ModelViewSet): # queryset = Books.objects.all() # serializer_class = BookSerializers # 查询所有和查询单个,如果只继承了ReadOnlyModelViewSet,路由也需要更改。 # class BookAPIView(ReadOnlyModelViewSet): # queryset = Books.objects.all() # serializer_class = BookSerializers # GenericViewSet:继承了(ViewSetMixin, generics.GenericAPIView) # ViewSet:继承了(ViewSetMixin, views.APIView) class BookAPIView(ViewSet): def xjz(self, request): return Response("junjie")
url
# 自动生成路由 from rest_framework.routers import SimpleRouter router = SimpleRouter() # 必须继承(ViewSetMixin),才能自动生成路由 router.register('books', views.BookAPIView) urlpatterns = [ path('admin/', admin.site.urls), # 将请求映射到对应的方法 path('books/', views.BookAPIView.as_view({'get':'list'})), path('books/<int:pk>', views.BookAPIView.as_view({'get':'retrieve'})), ] urlpatterns += router.urls
导入模块
from rest_framework.routers import SimpleRouter from django.urls import path,include
router = SimpleRouter() # 必须继承(ViewSetMixin),才能自动生成路由 router.register('admin', views.BookAPIView) urlpatterns = [ # path('admin/', admin.site.urls), path('api/',include(router.urls)) ]
此时浏览器访问admin的路由:http://127.0.0.1:8000/api/admin/
合集:
python_django
分类:
编程相关 / Python
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了