12_04、视图组件
一、APIView
APIView继承了View
是drf的顶层视图,上一节就是利用APIView写的五个接口
from rest_framework.views import APIView
APIView的类属性
renderer_classes
parser_classes
APIView与View对比
get方法,post方法,delete方法写法跟之前的View一样,只不过request对象变成了新的reques对象
比之前的View多了三大认证和全局异常处理
二、GenericAPIView
GenericAPIView,继承了APIView ,多了属性和方法
from rest_framework.generics import GenericAPIView
GenericAPIView的重要属性
queryset = None
serializer_class = None
GenericAPIView的重要方法
get_queryset
get_object
get_serializer
利用GenericAPIView写出五个接口

# 第二层:继承GenericAPIView写视图类 from rest_framework.generics import GenericAPIView class PublishView(GenericAPIView): queryset = Publish.objects.all() serializer_class = PublishSerialzier def get(self, request): # obj = self.queryset obj = self.get_queryset() # 等同于上面,更好一些 # ser = self.serializers(instance=obj,many=True) # ser=self.get_serializer_class()(instance=obj,many=True) # 等同于上面 ser = self.get_serializer(instance=obj, many=True) # 等同于上面 return Response(ser.data) def post(self, request): # ser = BookSerializer(data=request.data) ser = self.get_serializer(data=request.data) # 等同于上面 if ser.is_valid(): ser.save() return Response({"code": 100, 'msg': '新增成功', 'data': ser.data}) return Response({"code": 101, 'msg': '新增出错', 'err': ser.errors}) class PublishDetailView(GenericAPIView): queryset = Publish.objects.all() serializer_class = PublishSerialzier # lookup_field = 'pk' def get(self, request, *args, **kwargs): # book = Book.objects.all().filter(pk=pk).first() obj = self.get_object() # 等同于上面 # ser = BookSerializer(instance=book) ser = self.get_serializer(instance=obj) # 等同于上面 return Response(ser.data) def put(self, request, *args, **kwargs): # book = Book.objects.all().filter(pk=pk).first() obj = self.get_object() # 等同于上面 # ser = BookSerializer(instance=book, data=request.data) ser = self.get_serializer(instance=obj, data=request.data) # 等同于上面 if ser.is_valid(): ser.save() return Response({"code": 100, 'msg': '修改成功', 'data': ser.data}) return Response({"code": 101, 'msg': '修改出错', 'err': ser.errors}) def delete(self, request, *args, **kwargs): # Book.objects.filter(pk=pk).delete() self.get_object().delete() return Response({"code": 100, 'msg': '删除成功'})
路由

from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('publishs/', views.PublishView.as_view()), path('publishs/<int:pk>', views.PublishDetailView.as_view()), ]
三、5个视图扩展类
5个视图扩展类不是视图类,没有继承APIView,需要配合GenericAPIView
目的在于进一步方便我们编写五个接口
from rest_framework.generics import GenericAPIView from rest_framework.mixins import CreateModelMixin,ListModelMixin,DestroyModelMixin,RetrieveModelMixin,UpdateModelMixin
利用5个视图扩展类和GenericAPIView,写出五个接口

## 第三层:GenericAPIView+5个视图扩展类 from rest_framework.generics import GenericAPIView from rest_framework.mixins import CreateModelMixin, ListModelMixin, DestroyModelMixin, RetrieveModelMixin, \ UpdateModelMixin class PublishView(GenericAPIView, CreateModelMixin, ListModelMixin): queryset = Publish.objects.all() serializer_class = PublishSerialzier def get(self, request): return super().list(request) # create(request)ListModelMixin的方法 def post(self, request): return super().create(request) # create(request)CreateModelMixin的方法 class PublishDetailView(GenericAPIView, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin): queryset = Publish.objects.all() serializer_class = PublishSerialzier # lookup_field = 'pk' def get(self, request, *args, **kwargs): return super().retrieve(request, *args, **kwargs) def put(self, request, *args, **kwargs): return super().update(request, *args, **kwargs) def delete(self, request, *args, **kwargs): return super().destroy(request, *args, **kwargs)
四、9个视图子类
9个视图子类,是通过对GenericAPIView和5个视图扩展类进一步封装后,产生的新的视图类
from rest_framework.generics import CreateAPIView, ListAPIView, DestroyAPIView, RetrieveAPIView, UpdateAPIView from rest_framework.generics import ListCreateAPIView,RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView,RetrieveDestroyAPIView
9个视图子类就是九种接口
注意,实际项目中,我们可能会通过重写get、post或其他方法,提高接口的扩展性
CreateAPIView, # 新增一个 ListAPIView, # 查询所有 DestroyAPIView, # 删除一个 RetrieveAPIView, # 查询一个 UpdateAPIView # 修改一个
ListCreateAPIView, # 查询所有、新增一个 RetrieveUpdateAPIView, # 查询单条、更新 RetrieveUpdateDestroyAPIView, # 查询单条、更新、删除 RetrieveDestroyAPIView # 查询单条、删除
利用9个视图子类写九个接口

# 第四层:通过9个视图子类,编写视图函数 from rest_framework.generics import CreateAPIView, ListAPIView, DestroyAPIView, RetrieveAPIView, UpdateAPIView from rest_framework.generics import ListCreateAPIView, RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView, \ RetrieveDestroyAPIView # class PublishView(ListCreateAPIView): # 查询所有和新增接口就有了 # class PublishView(CreateAPIView): # 新增接口就有了 class PublishView(ListAPIView): # 查询所有接口就有了 queryset = Publish.objects.all() serializer_class = PublishSerialzier # 有可能要重写--》get_queryset--》get_serializer_class--》perform_create--》get,post方法 # 提高扩展性 class PublishDetailView(RetrieveUpdateDestroyAPIView): # 查询单条,删除,修改 # class PublishDetailView(RetrieveAPIView): # 查询单条 # class PublishDetailView(DestroyAPIView): # 删除 # class PublishDetailView(UpdateAPIView): # 修改 # class PublishDetailView(RetrieveDestroyAPIView): # 查询单条和删除 # class PublishDetailView(RetrieveUpdateAPIView): # 查询单条和更新 # class PublishDetailView(UpdateAPIView,DestroyAPIView): # 更新和删除,这个没有提供,我们自己组合 queryset = Publish.objects.all() serializer_class = PublishSerialzier
五、ViewSet
第一层,通过继承APIView,写出5个接口
第二层,通过继承GenericAPIView,写出5个接口,封装了第一层的类属性,简化了类方法
第三层,通过五个视图扩展类,配合第二层的GenericAPIView,写出5个接口,进一步简化类方法
第四层,通过9个视图子类,细化出了九种接口,我们可以根据需要自行选择其中一种或多种
第五层,就是VIewSet,通过一个视图类,可以写出全部的5个接口
from rest_framework.viewsets import ModelViewSet # 5个接口 from rest_framework.viewsets import ReadOnlyModelViewSet # 查询单个和所有接口
# 二者同级
利用一个ViewSet写出所有接口(ModelViewSet、ReadOnlyModelViewSet)
class PublishView1(ModelViewSet): # 5个接口 queryset = Publish.objects.all() serializer_class = PublishSerialzier class PublishView2(ReadOnlyModelViewSet): # 查所有,查单个(需要修改路由) queryset = Publish.objects.all() serializer_class = PublishSerialzier
需要注意的是,虽然我们通过一个视图写了五个接口,但是这里面有两个get(查询一个、查询所有),所以这里需要我们重新配置路由
这里提供两种路由配置方式
方式一:

from django.contrib import admin from django.urls import path, include from app01 import views from rest_framework.routers import SimpleRouter, DefaultRouter # router = DefaultRouter() router = SimpleRouter() router.register('publish', views.PublishView, 'publish') router.register('test', views.TestView, 'test') urlpatterns = [ path('admin/', admin.site.urls), # 方式1 (这种方式方便我们定制路由写法) path('api/v1/', include(router.urls)), # 等同于下面 # path('api/v1/publish/', views.BookView.as_view()), # path('api/v1/publish/<int:pk>', views.BookView.as_view()), ]
方式二:

from django.contrib import admin from django.urls import path, include from app01 import views from rest_framework.routers import SimpleRouter, DefaultRouter # router = DefaultRouter() router = SimpleRouter() router.register('publish', views.PublishView, 'publish') router.register('test', views.TestView, 'test') urlpatterns = [ path('admin/', admin.site.urls), ] # 方式二 # 把路由加入到urlpatterns的列表中 urlpatterns += router.urls # 两个列表相加 # router.urls 他会自动生成列表 publishs/和publishs/<int:pk>
补充:自动生成路由ViewSetMixin
之前我们手动配置路由,通过ViewSetMixin可以控制自动生成路由
所以以后只要想自动生成路由,必须继承ViewSetMixin及其子类
ViewSetMixin的子类:ViewSet,GenericViewSet
ViewSet=APIView+ViewSetMixin
GenericViewSet=GenericAPIView+ViewSetMixin
# 之前的写法可以沿用,只是如果要自动生成路由可以选择继承ViewSet,GenericViewSet from rest_framework.viewsets import ViewSet,GenericViewSet from rest_framework.viewsets import ViewSetMixin
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通