四、drf视图组件

drf视图组件

一、基于APIView

  • models.py

    from django.db import models
    class Book(models.Model):
        id = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5,decimal_places=2)
        publish = models.CharField(max_length=32)
        author = models.CharField(max_length=32)
    
  • ser.py(自定义序列化文件)

    from app01 import models
    from rest_framework import serializers
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
    
  • view.py

    from app01 import models
    from app01.ser import BookSerializer
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    # 自定义一个Response对象
    class MyResponse():
        def __init__(self):
            self.status = '1000'
            self.msg = '成功'
        @property
        def get_dict(self):
            return self.__dict__
    
    class BookView1(APIView):
        # 查询一条数据
        def get(self,request,pk):
            response_msg = MyResponse()
            book_obj = models.Book.objects.filter(id=pk).first()
            book_ser = BookSerializer(instance=book_obj)
            response_msg.data = book_ser.data
            return Response(response_msg.get_dict)
    
        # 删除一条数据
        def delete(self,request,pk):
            response_msg = MyResponse()
            models.Book.objects.filter(pk=pk).delete()
            response_msg.msg = '删除成功'
            return Response(response_msg.get_dict)
    
        # 修改一条数据
        def put(self,request,pk):
            response_msg = MyResponse()
            book_obj = models.Book.objects.filter(pk=pk).first()
            book_ser = BookSerializer(instance=book_obj,data=request.data)
            if book_ser.is_valid():
                book_ser.save()
                response_msg.data = book_ser.data
            else:
                response_msg.status = '1001'
                response_msg.msg = '校验失败,请稍后再试'
                response_msg.data = book_ser.errors
            return Response(response_msg.get_dict)
    class BooksView1(APIView):
        # 查询所有数据
        def get(self,request):
            response_msg = MyResponse()
            books_obj = models.Book.objects.all()
            books_ser = BookSerializer(instance=books_obj,many=True)
            response_msg.data = books_ser.data
            return Response(response_msg.get_dict)
    
        # 新增一条数据
        def post(self,request):
            response_msg = MyResponse()
            book_ser = BookSerializer(data=request.data)
            if book_ser.is_valid():
                book_ser.save()
                response_msg.msg = '新增成功'
                response_msg.data = book_ser.data
            else:
                response_msg.status = '1001'
                response_msg.msg = '新增失败,情稍后再试'
                response_msg.data = book_ser.errors
            return Response(response_msg.get_dict)
    
  • urls.py

    url(r'^book1/(?P<pk>\d+)', views.BookView1.as_view()),
    url(r'^books1/', views.BooksView1.as_view()),
    
  • 总结

    1. 继承关系: APIView继承View
    2. APIView基于View的拓展:
        APIView重写了View的dispatch方法, 在该方法中实现了实现了一下功能:
        (1) 对来的原生请求对象request进行了封装.
        (2) 提供了对包装过后的请求对象的三段认证: 认证, 权限控制, 频率控制
        (3) 重写了View中通过本次请求的方式动态的反射到自定义继承APIView类实例化的对象中定义的请求方法
        (4) 使用异常处理处理2,3步骤中的异常
        (5) 处理完毕异常以后使用drf的response对象对请求响应
    3. 针对路由配置
        路由中的有名分组必须指定pk, 视图中使用必须使用相同的关键字参数接受
    

二、基于GenericView

  • models.py

    from django.db import models
    class Book(models.Model):
        id = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5,decimal_places=2)
        publish = models.CharField(max_length=32)
        author = models.CharField(max_length=32)
    
  • ser.py(自定义序列化文件)

    # 最好使用ModelSerializer类,不用重写update和create方法
    from app01 import models
    from rest_framework import serializers
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
    
  • view.py

    from rest_framework.generics import GenericAPIView
    class BookGenericView2(GenericAPIView):
        # queryset要传queryset对象,查询了所有的图书
        # serializer_class使用哪个序列化类来序列化这堆数据
        queryset = models.Book.objects
        serializer_class = BookSerializer
        # queryset=models.Book.objects.all()
        # 查询一条数据
        def get(self,request,pk):
            response_msg = MyResponse()
            book_obj = self.get_object()
            book_ser = self.get_serializer(book_obj)
            response_msg.data = book_ser.data
            return Response(response_msg.get_dict)
    
        # 删除一条数据
        def delete(self,request,pk):
            response_msg = MyResponse()
            self.get_object().delete()
            response_msg.msg = '删除成功'
            return Response(response_msg.get_dict)
    
        # 修改一条数据
        def put(self,request,pk):
            response_msg = MyResponse()
            book_obj = self.get_object()
            book_ser = self.get_serializer(book_obj,request.data)
            if book_ser.is_valid():
                book_ser.save()
                response_msg.data = book_ser.data
            else:
                response_msg.status = '1001'
                response_msg.msg = '校验失败,请稍后再试'
                response_msg.data = book_ser.errors
            return Response(response_msg.get_dict)
    class BooksGenericView2(GenericAPIView):
        # queryset要传queryset对象,查询了所有的图书
        # serializer_class使用哪个序列化类来序列化这堆数据
        queryset = models.Book.objects
        serializer_class = BookSerializer
        # queryset=models.Book.objects.all()
        # 查询所有数据
        def get(self,request):
            response_msg = MyResponse()
            books_obj = self.get_queryset()
            books_ser = self.get_serializer(books_obj,many=True)
            response_msg.data = books_ser.data
            return Response(response_msg.get_dict)
    
        # 新增一条数据
        def post(self,request):
            response_msg = MyResponse()
            book_ser = self.get_serializer(data=request.data)
            if book_ser.is_valid():
                book_ser.save()
                response_msg.msg = '新增成功'
                response_msg.data = book_ser.data
            else:
                response_msg.status = '1001'
                response_msg.msg = '新增失败,情稍后再试'
                response_msg.data = book_ser.errors
            return Response(response_msg.get_dict)
    
  • urls.py

    url(r'^bookG2/(?P<pk>\d+)',views.BookGenericView2.as_view()),
    url(r'^bookGs2/',views.BooksGenericView2.as_view()),
    
  • 总结

    1.GenericAPIView继承自APIView,它在APIView的功能上增加了两个功能:
    	- 通用的模型类(传入需要序列化的模型数据)	queryset = None; 
    	- 通用的序列化器(传入对应的序列化器对象)	serializer_class = None
      	- 通用的有名分组名
        	lookup_field = 'pk':好像不能改
            lookup_url_kwarg = None:可以改,改成自己的有名分组名即可
    2.三个常用方法
    	- get_queryset() # 获取queryset对象,用于查询多条数据
    	- get_object()	# 获取一条对象数据
    	- get_serializer(*args, **kwargs)	# 获取序列化器对象,该传什么参数就传什么参数
    4.在写视图类时,模型表必须是queryset对象(加上objects),即queryset = Book.objects
    5.
    

三、基于GenericView+5个视图拓展类

  • models.py

    from django.db import models
    class Book(models.Model):
        id = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5,decimal_places=2)
        publish = models.CharField(max_length=32)
        author = models.CharField(max_length=32)
    
  • ser.py(自定义序列化文件)

    # 最好使用ModelSerializer类,不用重写update和create方法
    from app01 import models
    from rest_framework import serializers
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
    
  • view.py

    from  rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin
    class BookGenericView3(GenericAPIView,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin):
        """
        UpdateModelMixin:修改
        DestroyModelMixin:删除
        RetrieveModelMixin:查询一条数据
        """
        # queryset要传queryset对象,查询了所有的图书
        # serializer_class使用哪个序列化类来序列化这堆数据
        queryset = models.Book.objects
        serializer_class = BookSerializer
        # 查询一条数据
        def get(self,request,pk):
            return self.retrieve(request,pk)
    
        # 删除一条数据
        def delete(self,request,pk):
            return self.destroy(request,pk)
    
        # 修改一条数据
        def put(self,request,pk):
            return self.update(request,pk)
    class BooksGenericView3(GenericAPIView,ListModelMixin,CreateModelMixin):
        """
        ListModelMixin:查询所有
        CreateModelMixin:创建一条数据
        """
        # queryset要传queryset对象,查询了所有的图书
        # serializer_class使用哪个序列化类来序列化这堆数据
        queryset = models.Book.objects
        serializer_class = BookSerializer
        # queryset=models.Book.objects.all()
        # 查询所有数据
        def get(self,request):
            return self.list(request)
    
        # 新增一条数据
        def post(self,request):
            return self.create(request)
    
  • urls.py

    url(r'^bookG3/(?P<pk>\d+)',views.BookGenericView3.as_view()),
    url(r'^bookGs3/',views.BooksGenericView3.as_view()),
    
  • 总结

    1.使用GenericAPIView写不同类的接口,只是queryset参数和serializer_class参数的不同,其他的方法几乎完全一样
    2.这五个扩展类需要搭配GenericAPIView父类,因为五个扩展类的实现需要调用GenericAPIView提供的序列化器与数据库查询的方法。
    3.DestroyModelMixin、RetrieveModelMixin、UpdateModelMixin的路由中,必须使用pk
    
    # ListModelMixin 	     内部封装了list方法, 实现了查询所有数据
    	提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。
        该Mixin的list方法会对数据进行过滤和分页。
    # CreateModelMixin 		 内部封装了create方法, 实现了新增一条数据
    	提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。
    	如果序列化器对前端发送的数据验证失败,返回400错误。
    # RetrieveModelMixin	 内部封装了retrieve方法, 实现了查询一条数据
    	提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。
    	如果存在,返回200, 否则返回404。
    # UpdateModelMixin       内部封装了update方法, 实现了更新一条数据
     	提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。
        同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。
        成功返回200,序列化器校验数据失败时,返回400错误。
    # DestroyModelMixin      内部封装了destroy方法,实现了删除一条数据
    	提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。
    	成功返回204,不存在返回404。
    4.在写视图类时,模型表必须是queryset对象(加上objects),即queryset = Book.objects
    

四、基于GenericView+九个拓展类

  • models.py

    from django.db import models
    class Book(models.Model):
        id = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5,decimal_places=2)
        publish = models.CharField(max_length=32)
        author = models.CharField(max_length=32)
    
  • ser.py(自定义序列化文件)

    # 最好使用ModelSerializer类,不用重写update和create方法
    from app01 import models
    from rest_framework import serializers
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
    
  • view.py

    from rest_framework.generics import GenericAPIView,
        CreateAPIView, DestroyAPIView, UpdateAPIView, ListAPIView, RetrieveAPIView, 
        ListCreateAPIView, RetrieveDestroyAPIView, RetrieveUpdateDestroyAPIView, RetrieveUpdateAPIView
    
    # 创建一个数据
    class BookCreateAPIView(CreateAPIView):
        queryset = Book.objects
        serializer_class = BookModelSerializer
    
    # 删除一个数据
    class BookDestroyAPIView(DestroyAPIView):
        queryset = Book.objects
        serializer_class = BookModelSerializer
        
    # 修改一个数据
    class BookUpdateAPIView(UpdateAPIView):
        queryset = Book.objects
        serializer_class = BookModelSerializer
        
    # 获取所有数据
    class BookListAPIView(ListAPIView):
        queryset = Book.objects
        serializer_class = BookModelSerializer
    # 获取一个数据
    class BookRetrieveAPIView(RetrieveAPIView):
        queryset = Book.objects
        serializer_class = BookModelSerializer
        
    # 获取所有数据和创造一个数据
    class BookListCreateAPIView(ListCreateAPIView):
        queryset = Book.objects
        serializer_class = BookModelSerializer
    
    # 获取一个数据和删除一个数据
    class BookRetrieveDestroyAPIView(RetrieveDestroyAPIView):
        queryset = Book.objects
        serializer_class = BookModelSerializer
    
    # 获取一个数据和修改一个数据
    class BookRetrieveUpdateAPIView(RetrieveUpdateAPIView):
        queryset = Book.objects
        serializer_class = BookModelSerializer
       
    # 获取一个数据和修改一个数据和删除一个数据
    class BookRetrieveUpdateDestroyAPIView(RetrieveUpdateDestroyAPIView):
        queryset = Book.objects
        serializer_class = BookModelSerializer
    
  • urls.py

    url(r'^books/$', views.BookModelViewSet.as_view(),
    url(r'^books/(?P<pk>\d+)',views.BookModelViewSet.as_view(),
    
  • 总结

    1.不需要指定路由的actions参数,因为根本就没有
    2.在写视图类时,模型表必须是queryset对象(加上objects),即queryset = Book.objects
    

五、基于ModelViewSet

  • models.py

    from django.db import models
    class Book(models.Model):
        id = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5,decimal_places=2)
        publish = models.CharField(max_length=32)
        author = models.CharField(max_length=32)
    
  • ser.py(自定义序列化文件)

    # 最好使用ModelSerializer类,不用重写update和create方法
    from app01 import models
    from rest_framework import serializers
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
    
  • view.py

    from rest_framework.viewsets import ModelViewSet
    class BookGenericView4(ModelViewSet):
        """
        5个接口都有,但是路由有点问题
        问?怎么区别那种请求触发该请求方式的方法
        需要在路由中添加一个参数:actions={'get':'list','post':'create','get':'retrieve','delete':'destroy','put':'update'}
        """
        queryset = models.Book.objects
        serializer_class = BookSerializer
    
  • urls.py

    url(r'^bookG4/(?P<pk>\d+)', views.BookGenericView4.as_view(actions={'delete':'destroy','get':'retrieve','put':'update'})), # 这个路由中有删除一个、查询一个、修改一个的请求
        url(r'^bookGs4/', views.BookGenericView4.as_view(actions={'get':'list','post':'create'})), # 这个路由中有查询所有、增添一个的请求
    
  • 总结

    1.路由处的as_view()中必须传一个action参数(字典),格式:action={'get':'list','post':'creat'}
    2.在写视图类时,模型表必须是queryset对象(加上objects),即queryset = Book.objects
    

六、继承ViewSetMixin

  • models.py

    from django.db import models
    class Book(models.Model):
        id = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5,decimal_places=2)
        publish = models.CharField(max_length=32)
        author = models.CharField(max_length=32)
    
  • ser.py(自定义序列化文件)

    # 最好使用ModelSerializer类,不用重写update和create方法
    from app01 import models
    from rest_framework import serializers
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
    
  • view.py

    from rest_framework.viewsets import ViewSetMixin
    class BookGenericView5(ViewSetMixin,GenericAPIView):
        queryset = models.Book.objects
        serializer_class = BookSerializer
        # 查询一条数据
        def get_one_data(self,request,pk):
            response_msg = MyResponse()
            book_obj = self.get_object()
            book_ser = self.get_serializer(book_obj)
            response_msg.data = book_ser.data
            return Response(response_msg.get_dict)
    
        # 删除一条数据
        def delete_one_data(self,request,pk):
            response_msg = MyResponse()
            self.get_object().delete()
            response_msg.msg = '删除成功'
            return Response(response_msg.get_dict)
    
        # 修改一条数据
        def put_one_data(self,request,pk):
            response_msg = MyResponse()
            book_obj = self.get_object()
            book_ser = self.get_serializer(book_obj,request.data)
            if book_ser.is_valid():
                book_ser.save()
                response_msg.data = book_ser.data
            else:
                response_msg.status = '1001'
                response_msg.msg = '校验失败,请稍后再试'
                response_msg.data = book_ser.errors
            return Response(response_msg.get_dict)
    class BooksGenericView5(ViewSetMixin,GenericAPIView):
        queryset = models.Book.objects
        serializer_class = BookSerializer
        # 查询所有数据
        def get_all_data(self,request):
            response_msg = MyResponse()
            books_obj = self.get_queryset()
            books_ser = self.get_serializer(books_obj,many=True)
            response_msg.data = books_ser.data
            return Response(response_msg.get_dict)
    
        # 新增一条数据
        def post_one_data(self,request):
            response_msg = MyResponse()
            book_ser = self.get_serializer(data=request.data)
            if book_ser.is_valid():
                book_ser.save()
                response_msg.msg = '新增成功'
                response_msg.data = book_ser.data
            else:
                response_msg.status = '1001'
                response_msg.msg = '新增失败,情稍后再试'
                response_msg.data = book_ser.errors
            return Response(response_msg.get_dict)
    
  • urls.py

    url(r'^bookG5/(?P<pk>\d+)', views.BookGenericView5.as_view(actions={'delete':'delete_one_data','get':'get_one_data','put':'put_one_data'})), # 这个路由中有删除一个、查询一个、修改一个的请求
        url(r'^bookGs5/', views.BooksGenericView5.as_view(actions={'get':'get_all_data','post':'post_one_data'})), # 这个路由中有查询所有、增添一个的请求
    
  • 总结

    1.ViewSetMixin类一定要放在GenericAPIView类前面
    2.ViewSetMixin类可以与APIView类使用,请求函数和使用APIView类时一样,只不过可以自定义自己的请求方式名
    	def get_all_data(,self,request):
            pass
    3.自定义自己的请求方式函数时,需要在路由的as_view()中的action中设置好映射关系
    	url(r'^index/',view.Data.as_view(action={'get':'get_all_data'}))
    4.在写视图类时,模型表必须是queryset对象(加上objects),即queryset = Book.objects
    
posted @ 2021-01-26 15:51  今天捡到一百块钱  阅读(89)  评论(2编辑  收藏  举报