Django Rest Framework 视图集

视图集ViewSet

视图集的继承关系
Django Rest Framework 视图集_第1张图片
视图集类继承关系.png
两个基本视图集
视图集 继承自
Viewset APIView,ViewSetMixin
GenricViewset GenericAPIView,ViewSetMixin
  • ViewSet
    • 在ViewSet中,没有提供任何动作action方法,需自己实现动作action( list() 、create() 等)
    • 因为继承自ViewSetMixin,实现了将请求方式和action动作在as_view中进行映射,键值对中,值可以相同,键必须不同
      as_view({'请求方式1':'action动作1','请求方式2':'action动作2',})
  • GenricViewSet
class BooksViewSet(ViewSet):
    def list(self, request):
        #获取所有数据
        books = BookInfo.objects.all()
        ser = BookSerializers(books, many=True)
        return Response(ser.data)

    def create(self, request):
        #保存数据
        data = request.data
        ser = BookSerializers(data=data)
        ser.is_valid(raise_exception=True)
        ser.save()
        return Response(ser.data)

    def last(self, request):
        #返回最后一本图书信息
        book = BookInfo.objects.last()
        ser = BookSerializers(book)
        return Response(ser.data)

    def show(self, request, pk):
        #获取指定数据
        book = BookInfo.objects.get(id=pk)
        ser = BookSerializers(book)
        return Response(ser.data)
两个扩展视图集
扩展视图集 继承自
ModelViewset GenricViewset,五个扩展类
ReadOnlyModelViewSet GenricViewset,ListModelMixin,RetrieveModelMixin
  • ModelViewset
    • 继承自GenericAPIVIew、ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin
  • ReadOnlyModelViewSet
    • 参与序列化返回,所以继承自查询单个数据和查询所有数据的扩展类
#定义一个分页
class PageNum(PageNumberPagination):
    page_size_query_param = 'page_size'  #指定控制页面展示数量的参数
    max_page_size = 8  #最大返回多少条数据

class BooksModelViewSet(ModelViewSet):
    serializer_class = BookSerializers
    queryset = BookInfo.objects.all()
    #局部认证属性
    # authentication_classes = [BasicAuthentication, SessionAuthentication]
    #局部权限属性
    # permission_classes = [IsAuthenticated]
    #局部限流属性
    # throttle_classes = [UserRateThrottle]
    #对视图进行限流命名, 在setting.py中进行限流次数的指定
    # throttle_scope = 'shows'
    #过滤字段指定
    # filter_fields = ('btitle', 'bread')
    # #排序过滤
    # #指定过滤的类方法
    # filter_backends = [OrderingFilter]
    # #针对排序的字段定义
    # ordering_fields = ['id', 'bread']
    #局部配置 分页属性
    # pagination_class = PageNum

    @action(methods=['get'], detail=True)
    def show(self, request, pk):
        #手动抛出一个异常
        # raise DataError
        #获取指定数据
        book = self.get_object()
        ser = self.get_serializer(book)
        return Response(ser.data)
视图集自定义action动作

在视图集中,除了默认的动作(list() 提供一组数据,retrieve() 提供单个数据,create() 创建数据,update() 保存数据,destory() 删除数据)外,可以自定义动作

  • 添加自定义动作时,需要rest_framework.decorators.action装饰器
  • 在自定义动作方法上,添加@action(),接收两个参数
    • methods,该action支持的请求方式,列表传递
    • detail,action中要处理的是否是视图资源的对象(即是否通过url路径获取主键)
      • True 表示使用通过URL获取的主键对应的数据对象
      • False 表示不使用URL获取主键

路由Router

SimpleRouter
  1. 创建router,并注册视图集
  • register(prefix, viewset, base_name)
    • prefix 该视图集的路由前缀
    • viewset 视图集
    • base_name 路由名称的前缀
from rest_framework import routers

router = routers.SimpleRouter()
router.register(r'books', BookInfoViewSet, base_name='book')
  1. 添加路由数据
  • 在注册之后,urlpatterns += router.urls
  • 直接在urlpatterns中includerouter.url
    • url(r'^', include(router.urls))
  1. 视图集中使用装饰器@action,在视图类内自定义的方法上添加自动生成路由
  • @action(methods=['get'], detail=False)
    • detail为False,生成的路由中不会有正则匹配(方法中不接收参数)
    • detail为True,生成的路由中有正则匹配(方法中接收参数)
DefaultRouter

DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据

因为视图集继承自ViewSetMixin,才有action属性,装饰器和自动生成路由的方法

认证,权限和限流属性(APIView)

  • authentication_classes认证属性
    • 全局认证,在settings.py的REST_FRAMEWORK中定义 'DEFAULT_AUTHENTICATION_CLASSES'
    • 局部认证,在类视图中定义authentication_classes = (SessionAuthentication, BasicAuthentication)
  • permission_classes 权限认证
    • 权限控制可以限制用户对于视图的访问和对于具体数据对象的访问
      • 在执行视图的dispatch()方法前,会先进行视图访问权限的判断
      • 在通过get_object()获取具体对象时,会进行对象访问权限的判断
    • 提供的权限
      • AllowAny 允许所有用户
      • IsAuthenticated 仅通过认证的用户
      • IsAdminUser 仅管理员用户
      • IsAuthenticatedOrReadOnly 认证的用户可以完全操作,否则只能get读取
    • 全局配置,在settings.py的REST_FRAMEWORK中定义 'DEFAULT_PERMISSION_CLASSES',
    • 局部配置,在类视图中定义permission_classes = (IsAuthenticated,)
  • throttle_classes限流属性
    • 全局配置,在settings.py的REST_FRAMEWORK中定义DEFAULT_THROTTLE_CLASSES (限流类)和 DEFAULT_THROTTLE_RATES(限流周期)
      • 可选限流类
        • AnonRateThrottle,限制所有匿名未认证用户,DEFAULT_THROTTLE_RATES['anon'] 来设置频次
        • UserRateThrottle,限制认证用户,DEFAULT_THROTTLE_RATES['user'] 来设置频次
        • ScopedRateThrottle,限制用户对于每个视图的访问频次,在视图类中用throttle_scope起别名,在settings.py中对别名进行频次设置
    • 局部配置,在类视图中定义throttle_classess=(UserRateThrottle,)

过滤与排序属性

  • 过滤
    • 安装django-filter
    pip insall django-filter
    
    • 将django-filter在settings.py中注册应用
    • 在settings.py中的REST_FRAMEWORK,定义'DEFAULT_FILTER_BACKENDS'
    • 在视图中添加filter_fields属性,指定可以过滤的字段
    • 在浏览器进行访问时,?字段=查询内容
  • 排序
    • 在试图类中设置filter_backends,使用rest_framework.filters.OrderingFilter过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。
    • 前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。
    • 不用在settings.py中做任何配置
    • 浏览器访问时,通过?ordering=字段,从小到大,-字段,从大到小
filter_backends = [OrderingFilter]
    ordering_fields = ('id', 'bread', 'bpub_date')
  • 过滤和排序不能同时使用

分页,异常处理和自动生成接口文档

  • 分页
    • 全局配置
      REST_FRAMEWORK = {
          'DEFAULT_PAGINATION_CLASS':  'rest_framework.pagination.PageNumberPagination',
          'PAGE_SIZE': 100  # 每页数目
      }
      
    • 局部配置
      -自定义Pagination类,为视图添加分页行为
      class LargeResultsSetPagination(PageNumberPagination):
          page_size = 1000
          page_size_query_param = 'page_size'
          max_page_size = 10000
      class BookDetailView(RetrieveAPIView):
          queryset = BookInfo.objects.all()
          serializer_class = BookInfoSerializer
          pagination_class = LargeResultsSetPagination
      
      • 可选分页器
        • PageNumberPagination
        • 前端访问:GET http://api.example.org/books/?page=4
        • 在子类中定义的属性
        page_size 每页数目
        page_query_param 前端发送的页数关键字名,默认为"page"
        page_size_query_param 前端发送的每页数目关键字名,默认为None
        max_page_size 前端最多能设置的每页数量
        
        from rest_framework.pagination import PageNumberPagination
        
        class StandardPageNumberPagination(PageNumberPagination):
            page_size_query_param = 'page_size'
            max_page_size = 10
        
        class BookListView(ListAPIView):
            queryset = BookInfo.objects.all().order_by('id')
            serializer_class = BookInfoSerializer
            pagination_class = StandardPageNumberPagination
        
        # 127.0.0.1/books/?page=1&page_size=2
        
        • LimitOffsetPagination
        • 前端访问形式:GET http://api.example.org/books/?limit=100&offset=400
        • 在子类中定义的属性
        default_limit 默认限制,默认值与PAGE_SIZE设置一直
        limit_query_param limit参数名,默认'limit'
        offset_query_param offset参数名,默认'offset'
        max_limit 最大limit限制,默认None
        
        from rest_framework.pagination import LimitOffsetPagination
        class BookListView(ListAPIView):
            queryset = BookInfo.objects.all().order_by('id')
            serializer_class = BookInfoSerializer
            pagination_class = LimitOffsetPagination
        
        # 127.0.0.1:8000/books/?offset=3&limit=2
        
  • 异常处理
    • 自定义异常处理
      #在类视图方法中先手动抛出异常
      
      #定义异常处理方法
      from rest_framework.views import exception_handler as drf_exception_handler
      
      def exception_handler(exc, context):
          # 先调用REST framework默认的异常处理方法获得标准错误响应对象
          response = drf_exception_handler(exc, context)
      
          # 在此处补充自定义的异常处理
          if response is None:
              view = context['view']
              if isinstance(exc, DataError):
                  print('[%s]: %s' % (view, exc))
                  response = Response({'detail': '服务器内部错误'},
                           status=status.HTTP_507_INSUFFICIENT_STORAGE)
      
          return response
      
      #在配置文件中声明
      REST_FRAMEWORK = {
          'EXCEPTION_HANDLER': 'book.utils.exception_handler'
      }
      
  • 自动生成接口文档
    • 接口文档以网页的方式呈现,自动接口文档能生成的是继承自APIView及其子类的视图

    • 安装依赖

      pip install coreapi

    • 设置接口文档访问路径

      • 在总路由中添加接口文档路径
      • 文档路由对应的视图配置为rest_framework.documentation.include_docs_urls
      from rest_framework.documentation import include_docs_urls
      
      urlpatterns = [
          ...
          url(r'^docs/', include_docs_urls(title='My API title'))
      ]
      
    • 文档描述说明的定义位置

      • 单一方法的视图,可直接使用类视图的文档字符串

        class BookListView(generics.ListAPIView):
            """
            返回所有图书信息.
            """
        
      • 包含多个方法的视图,在类视图的文档字符串中,分开方法定义

        class BookListCreateView(generics.ListCreateAPIView):
            """
            get:
            返回所有图书信息.
            post:
            新建图书.
            """
        
      • 对于视图集ViewSet,仍在类视图的文档字符串中分开定义,但是应使用action名称区分

        class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
            """
            list:
            返回图书列表数据
            retrieve:
            返回图书详情数据
            latest:
            返回最新的图书数据
            read:
            修改图书的阅读量
            """
        
    • 访问接口文档网页

      • 浏览器访问 127.0.0.1:8000/docs/,即可看到自动生成的接口文档
      • 视图集ViewSet中的retrieve名称,在接口文档网站中叫做read
      • 参数的Description需要在模型类或序列化器类的字段中以help_text选项定义

你可能感兴趣的:(Django Rest Framework 视图集)