drf 05——2个视图基类、5个视图拓展类、9个视图子类、视图集、路由组件
一、 2个视图基类
路由
path('books/', views.BookView.as_view()),
path('books/<int:pk>/', views.BookDetailView.as_view()),
视图层
# 通用包
from rest_framework.response import Response
from .models import Book
from .serializer import BookSerializer
APIView
使用APIView写5个接口
# 1 继承APIView写五个接口
from rest_framework.views import APIView
class BookView(APIView):
def get(self, request):
books = Book.objects.all()
ser = BookSerializer(instance=books, many=True)
return Response(ser.data)
def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response({'code': 101, 'msg': '创建失败', 'errors': ser.errors})
class BookDetailView(APIView):
def get(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book)
return Response(ser.data)
def delete(self, request, pk):
Book.objects.filter(pk=pk).delete()
return Response({'code': 100, 'msg': '删除成功'})
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book, data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '修改成功'})
else:
return Response({'code': 101, 'msg': '保存失败', 'errors': ser.errors})
GenericAPIView
# 2 继承GenericAPIView写5个接口
from rest_framework.generics import GenericAPIView
class BookView(GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self, request):
books = self.get_queryset()
ser = self.get_serializer(instance=books, 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)
else:
return Response({'code': 101, 'msg': '创建失败', 'errors': ser.errors})
class BookDetailView(GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self, request, *args, **kwargs):
book = self.get_object()
ser = self.get_serializer(instance=book)
return Response(ser.data)
def put(self, request, *args, **kwargs):
book = self.get_object()
ser = self.get_serializer(instance=book, data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '修改成功'})
else:
return Response({'code': 101, 'msg': '修改失败', 'errors': ser.errors})
def delete(self, request, *args, **kwargs):
self.get_object().delete()
return Response({'code': 100, 'msg': '删除成功'})
二、5个视图扩展类
视图拓展类
不是视图类
没有继承视图类(View、APIView及其子类)
"""
例:class ListModelMixin:
...
没有加()继承类
"""
这五个视图拓展类把五个接口的功能都写好了
ListModelMixin # 获取所有
CreateModelMixin # 创建一个
RetrieveModelMixin # 查询一个
UpdateModelMixin # 更新一个
DestroyModelMixin # 删除一个
# 3 继承GenericAPIView + 5个视图扩展类实现5个接口
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin
class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self, request):
return super().list(request)
def post(self, request):
return super().create(request)
class BookDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self, request, *args, **kwargs):
return super().retrieve(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return super().destroy(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return super().update(request, *args, **kwargs)
三、9个视图子类
继承自 5个视图拓展类 + GenericAPIView
进行视图拓展类的组合
# 获取所有,新增一个,获取所有和新建一个
ListAPIView,CreateAPIView,ListCreateAPIView
# 获取单个,更新一个,删除一个
RetrieveAPIView,UpdateAPIView,DestroyAPIView
RetrieveUpdateDestroyAPIView,RetrieveUpdateAPIView,RetrieveDestroyAPIView
# 继承9个视图子类后,只需要在视图类中写两个类属性即可
queryset =
serializer_class =
# 4 使用9个视图子类写5个接口
from rest_framework.generics import ListAPIView, CreateAPIView, ListCreateAPIView
from rest_framework.generics import RetrieveAPIView, UpdateAPIView, DestroyAPIView
from rest_framework.generics import RetrieveUpdateAPIView, RetrieveDestroyAPIView, RetrieveUpdateDestroyAPIView
class BookView(ListCreateAPIView):
queryset = Book.objects.all() # 要序列化的数据
serializer_class = BookSerializer # 序列化类
class BookDetailView(RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
四、视图集
class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
pass
# 五个视图拓展类:
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
每个类里有一个方法
create retrieve update destroy list
# GenericViewSet
ViewSetMixin + generics.GenericAPIView
2个视图基类之一
# ViewSetMixin
继承后,路由写法发生变化
as_view({'get': 'list', 'post': 'create'})
'例:'
path('books/', views.BookView.as_view({'get': 'list', 'post': 'create'})),
path('books/<int:pk>/', views.BookDetailView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
# ViewSetMixin 源码分析
class ViewSetMixin:
@classonlymethod
def as_view(cls, actions=None, **initkwargs):
# actions={'get': 'list', 'post': 'create'}
def view(request, *args, **kwargs):
# method:get action:list
for method, action in actions.items():
# handler就是list
handler = getattr(self, action) #视图类反射有没有list
# 反射:把get变成了list
setattr(self, method, handler)
return self.dispatch(request, *args, **kwargs)
return csrf_exempt(view)
# 如果请求来了,会执行 view(request)
# 视图集中的类
ViewSetMixin # 改变路由写法 可自定义路由
ViewSet 继承了'ViewSetMixin' + 'views.APIView'
自定义路由 + APIView
GenericViewSet 继承了'ViewSetMixin' + 'generics.GenericAPIView'
自定义路由 + GenericAPIView
ReadOnlyModelViewSet 继承了'mixins.RetrieveModelMixin' + 'mixins.ListModelMixin' + 'GenericViewSet'
查单个 + 查全部 + 自定义路由 + GenericAPIView
ModelViewSet 继承了'五个视图拓展类' + 'GenericViewSet'
全继承 自定义路由 + GenericAPIView
想继承'APIView' 又想'自动生成路由' 继承'ViewSet'
想继承'GenericAPIView' 又想'自动生成路由' 继承'GenericViewSet'
# 5. 使用视图集写5个接口+修改路由格式
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet, ViewSetMixin, ViewSet, GenericViewSet
class BookView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
# ReadOnlyModelViewSet
"""
继承了:
mixins.RetrieveModelMixin 获取单个
mixins.ListModelMixin 获取全部
GenericViewSet
所以只支持get
"""
class BookView(ReadOnlyModelViewSet): # 获取所有和获取单个
queryset = Book.objects.all()
serializer_class = BookSerializer
五、路由组件
继承了ViewSetMixin及其子类 路由写法发生变化
# 写法一
path('books/', views.BookView.as_view({'get': 'list', 'post': 'create'})),
path('books/<int:pk>/', views.BookDetailView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
# 写法二
1. 导入一个路由类
from rest_framework.routers import SimpleRouter, DefaultRouter
2. 实例化得到对象
# 方式一
SimpleRouter()
# 方式二
DefaultRouter()
"""
两种方式
区别:
DefaultRouter会给每个注册的视图类生成一个根路由
"""
3. 注册路由----使用视图类注册----能够自动生成路由
router.register('books', views.BookView, 'books')
4. 在总路由中注册
# 方式一
urlpatterns += router.urls
# 方式二
path('', include(router.urls)),
# action装饰器的用法
from rest_framework.decorators import action
class PublishView(ViewSetMixin, APIView):
# ViewSetMixin改了路由写法,变成映射关系了,在视图类中可以写任意的方法名
'''
methods:请求方式
detail:
False:是不是带id的路由 http://127.0.0.1/publish/3 http://127.0.0.1/publish
True: 生成的路由publish/pk/aaa/
url_path:如果不写,就是函数名生成的路径是:http://127.0.0.1/publish/lqz
url_name:别名
'''
"""
此处装饰器:
生成路径http://127.0.0.1/publish/aaa/
对该路径的GET POST请求都执行的aaa方法
"""
@action(methods=['POST', 'GET'], detail=False, url_path='aaa', url_name='aaa')
def aaa(self, request):
return Response('这个是aaa')
def bbb(self, request):
return Response('这个是bbb')
def ccc(self, request):
return Response('这个是ccc')
总结
2个视图基类
APIView GenericAPIView
GenericAPIView继承的APIView
他们都需要自己写请求方法 get post delete put
然后发送请求方式执行对应请求方式小写的方法
而GenericAPIView内有两个属性
queryset
serializer_class
单独拎出进行设置
5个视图拓展类
ListModelMixin # 获取所有
CreateModelMixin # 创建一个
RetrieveModelMixin # 查询一个
UpdateModelMixin # 更新一个
DestroyModelMixin # 删除一个
他们是单独的类 没有继承视图类(View、APIView及其子类)
他们封装了单个方法
现在根据GenericAPIView和五个视图拓展类就可以封装出更简单的写法
class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = Book.objects.all() # 两个属性
serializer_class = BookSerializer
def get(self, request):
return super().list(request) # 执行对应请求方式小写方法调用父类方法
def post(self, request):
return super().create(request)
9个视图子类
继承自'5个视图拓展类中单个或多个' + 'GenericAPIView'
相当于把'增单查全' '查单改单删单'进行组合
查单个 增单个 查单个和增单个
...
就可以不用继承多个视图拓展类 只要继承单个视图子类就够了 更加方便了
九个子类自己也把对应关系封装好了 比如POST请求就会执行对应的list方法
写法变成了:
class BookView(ListCreateAPIView):
queryset = Book.objects.all() # 要序列化的数据
serializer_class = BookSerializer # 序列化类
视图集
# 视图集中的类
ViewSetMixin # 改变路由写法 可自定义路由
ViewSet 继承了'ViewSetMixin' + 'views.APIView'
自定义路由 + APIView
GenericViewSet 继承了'ViewSetMixin' + 'generics.GenericAPIView'
自定义路由 + GenericAPIView
ReadOnlyModelViewSet 继承了'mixins.RetrieveModelMixin' + 'mixins.ListModelMixin' + 'GenericViewSet'
查单个 + 查全部 + 自定义路由 + GenericAPIView
ModelViewSet 继承了'五个视图拓展类' + 'GenericViewSet'
全继承 自定义路由 + GenericAPIView
想继承'APIView' 又想'自动生成路由' 继承'ViewSet' 需要自己写方法+路由方法映射
想继承'GenericAPIView' 又想'自动生成路由' 继承'GenericViewSet' 需要自己写方法+路由方法映射
继承了GenericViewSet的'ReadOnlyModelViewSet'和'ModelViewSet'
发送对应请求就会执行对应封装好的请求方法
只需要两个属性
queryset =
serializer_class =
只是 ReadOnlyModelViewSet 只支持get全部和get单个
ModelViewSet 因为继承了五个视图拓展类
get post delete put全支持
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?