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全支持

posted @   扶我上码  阅读(50)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示