• 欢迎光临~

2个视图基类、5 个视图扩展类、9个视图子类、视图集、路由组件

开发技术 开发技术 2022-06-18 次浏览

2个视图基类

# django 内置的View
# drf 的APIView ,继承自View
# GenericAPIView
--两个重要的类属性:
    -queryset = Book.objects.all()  # 要序列化的数据
    -serializer_class = BookSerializer  # 序列化类
--几个重要的方法:
    -self.get_queryset()  # 得到查询结果集
    -self.get_serializer(instance=book_list, )
    '''
    指定了查询结果集,就代表数据已经定了,接下来都是在这个查询结果集里面进行对数据库的增删查改了。
    要使用序列化器,直接 self.get_serializer()调用。
    '''
	-self.get_object()  # 得到单独的一个对象
    '''
    调用了self.get_object(),谁调用他,他就会先从那个调用他的函数中获取到名为pk的值,再将名为pk的值作为id条件,在查询结果集中进行匹配,匹配成功,将对象返回出来。
    '''

使用APIView写5个接口

class BookView(APIView):
    def get(self,request):
        book_list=Book.objects.all()
        # 如果写了many=True,ser是哪个类的对象?
        ser=BookSerializer(instance=book_list,many=True)
        print(type(ser)) # ListSerializer的对象---》[BookSerializer,BookSerializer,BookSerializer]
        return Response(ser.data)

    def post(self,request):
        ser=BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code':'100','msg':'创建成功'})
        else:
            return Response({'code': '101', 'msg': '创建失败','err':ser.errors})

class BookDetailView(APIView):
    def get(self,request,*args,**kwargs):  # pk 从kwargs中去
        book=Book.objects.filter(pk=kwargs['pk']).first()
        # 如果写了many=True,ser是哪个类的对象?
        ser=BookSerializer(instance=book)
        print(type(ser))  # BookSerializer的对象
        return Response(ser.data)

    #put:全局修改   patch:局部修改
    def put(self,request,*args,**kwargs):  # pk 从kwargs中去
        book=Book.objects.filter(pk=kwargs['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': '创建失败', 'err': ser.errors})

继承GenericAPIView写5个接口

'重点'
	-使用的方法属性
		-queryset = Book.objects.all()  # 要序列化的数据
        -serializer_class = BookSerializer  # 序列化类
	-继承父类
    	GenericAPIView
class BookView(GenericAPIView):
    queryset = Book.objects.all()  # 要序列化的数据
    serializer_class = BookSerializer  # 序列化类

    def get(self, request):
        print('dsafdasdfasd')
        book_list = self.get_queryset()  # 获取要序列化的数据,不要直接使用self.queryset,而要用self.get_queryset()

        # 获取序列化类,要使用self.get_serializer
        ser = self.get_serializer(instance=book_list, many=True)
        print(type(ser))  # ListSerializer的对象---》[BookSerializer,BookSerializer,BookSerializer]
        return Response(ser.data)

    def post(self, request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': '100', 'msg': '创建成功'})
        else:
            return Response({'code': '101', 'msg': '创建失败', 'err': ser.errors})


class BookDetailView(GenericAPIView):
    queryset = Book.objects.all()  # 要序列化的数据
    serializer_class = BookSerializer  # 序列化类
    #传入的必须叫pk,否则,get_object就拿不到对象
    def get(self, request, *args, **kwargs):
        # 获取单个对象,
        book = self.get_object()
        # 如果写了many=True,ser是哪个类的对象?
        ser = self.get_serializer(instance=book)
        print(type(ser))  # BookSerializer的对象
        return Response(ser.data)

    # put:全局修改   patch:局部修改
    def put(self, request, *args, **kwargs):  # pk 从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': '创建失败', 'err': ser.errors})

5 个视图扩展类

# 视图扩展类---》不是视图类---》没有继承视图类(View,APIView...子类)

ListModelMixin  # 获取所有
CreateModelMixin  # 创建一个
RetrieveModelMixin  # 查询一个
UpdateModelMixin  # 更新一个
DestroyModelMixin  # 删除一个
-需要搭配GenericAPIView使用
	eg:class Books(GenericAPIView, ListModelMixin, CreateModelMixin):

使用5个视图扩展类写五个接口

from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
class BookView(GenericAPIView,ListModelMixin,CreateModelMixin):
    queryset = Book.objects.all()  # 要序列化的数据
    serializer_class = BookSerializer  # 序列化类

    def get(self,request):
        print('获取所有')
        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  # 序列化类
    #传入的必须叫pk,否则,get_object就拿不到对象
    def get(self, request, *args, **kwargs):
        print('获取一')
        return super().retrieve(request, *args, **kwargs)

    # put:全局修改   patch:局部修改
    def put(self, request, *args, **kwargs):  # pk 从kwargs中去
        return super().update(request, *args, **kwargs)

    def delete(self,request, *args, **kwargs):
        return super().destroy(request, *args, **kwargs)

9个视图子类

'''9个视图子类'''
'''
ListAPIView  获取所有
CreateAPIView  新增一个
    -ListCreateAPIView  获取所有和新建一个

RetrieveAPIView  获取单个
UpdateAPIView  更新一个
DestroyAPIView  删除一个

    -RetrieveUpdateDestroyAPIView  获取单个更新一个删除一个
    -RetrieveUpdateAPIView  获取和更新
    -RetrieveDestroyAPIView  获取一个和删除一个

使用9个视图子类写五个接口

继承9个视图子类后,只需要在视图类中写两个类属性即可

class BookView(ListCreateAPIView):  # 获取所有和新增一个
    queryset = Book.objects.all()  # 要序列化的数据
    serializer_class = BookSerializer  # 序列化类

class BookDetailView(RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()  # 要序列化的数据
    serializer_class = BookSerializer  # 序列化类

视图集

# 视图集中的类
	-ModelViewSet
    -ReadOnlyModelViewSet
    -ViewSetMixin
    -ViewSet:ViewSetMixin+APIView
    -GenericViewSet:ViewSetMixin+GenericAPIView
    
# 以后你想继承APIView,但是路由想自动生成,继承ViewSet
# 以后想继承GenericAPIView,但是路由想自动生成,GenericViewSet

ModelViewSet

ModelViewSet是封装度最高的DRF的视图类。包含了增删改查中的所有接口操作。
继承GenericViewSet、ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

class UserView(ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

自定义action

    def 名称(self, request):
        '''
        自定义action
        :return: JSON数据
        '''
        pass

路由代码

path('user/', views.UserView.as_view({'post': 'action名称'})),

案例代码

class UserView(ModelViewSet):
    # @action(methods=['POST', ], detail=False, url_path='login', url_name='login')
    def login(self, request):
        user = User.objects.all()
        ser = UserSerializer(instance=user, data=request.data)
        if ser.is_valid():
            return Response({'msg': '登录成功'})
        else:
            return Response({'msg': '登录失败', 'err': ser.errors})
        
# 路由代码
    path('user/', views.UserView.as_view({'post': 'login'})),

ReadOnlyModelViewSet

  • 继承了

    mixins.RetrieveModelMixin,
    mixins.ListModelMixin,
    GenericViewSet
    
此方法提供了get请求多条与单条数据的方法

ViewSetMixin

需要搭配APIView一起使用

# ViewSetMixin 写在前面,先找ViewSetMixin的as_view方法
# 用了ViewSetMixin ,视图类中,不需要再写get,post,delete....这些函数了,函数名可以自定义
# 而且这个视图类,可以响应多条路由

ViewSet

包含了ViewSetMixin+APIView

GenericViewSet

包含了ViewSetMixin+GenericAPIView

总结

# 以后你想继承APIView,但是路由想自动生成,继承ViewSet
# 以后想继承GenericAPIView,但是路由想自动生成,GenericViewSet

路由组件

路由写法

# 1 继承了ViewSetMixin及其子类,路由写法变了
	-写法一:path('publish', views.PublishView.as_view({'get': 'lqz','post':'login'})),
    -写法二:自动生成
    # 第一步:导入一个路由类
    from rest_framework.routers import SimpleRouter, DefaultRouter

    # 第二步:实例化得到对象
    router=SimpleRouter()
    # router = DefaultRouter()  # 它会给每个注册的视图类都生成一个根路由
    # 第三步:注册路由---》使用视图类注册---》能自动生成路由
    router.register('books', views.BookView, 'books')
    router.register('publish', views.BookView, 'publish')
    # 第四步:在总路由中注册  方式二
    path('', include(router.urls)),
    # 第四步:在总路由中注册  方式一
	# urlpatterns+=router.urls

action装饰器的用法

-之前自动生成路由只能生成
    {'get': 'list', 'post': 'create'},{'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}
-使用action装饰器来做对应关系
path('user/', views.UserView.as_view({'post': 'login'})),
    @action(methods=['POST', ], detail=False, url_path='login', url_name='login')

        '''
        methods:请求方式
        detail:
            False:是不带id的路由  http://127.0.0.1/publish/3   
            http://127.0.0.1/publish
            True: 生成的路由publish/pk/lqz/
        url_path:如果不写,就是函数名生成的路径是:http://127.0.0.1/publish/lqz
        url_name:别名
        '''
  
    
喜欢 (0)