zoukankan      html  css  js  c++  java
  • 四、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
      
  • 相关阅读:
    Spring Boot 2.x实战之StateMachine
    Spring Boot实战之定制type Formatters
    Spring Boot实战之定制URL匹配规则
    Spring Boot项目中如何定制servlet-filters
    Mac高效开发之iTerm2、Prezto和Solarized主题
    Spring Boot应用的健康监控
    Spring Boot构建的Web项目如何在服务端校验表单输入
    Spring Boot项目中如何定制PropertyEditors
    Spring Boot项目中如何定制拦截器
    在Spring Boot项目中使用Spock测试框架
  • 原文地址:https://www.cnblogs.com/borntodie/p/14330777.html
Copyright © 2011-2022 走看看