视图集ViewSet
视图集的继承关系
两个基本视图集
视图集 | 继承自 |
---|---|
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
- 创建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')
- 添加路由数据
- 在注册之后,urlpatterns += router.urls
- 直接在urlpatterns中includerouter.url
- url(r'^', include(router.urls))
- 视图集中使用装饰器@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,)
- 全局配置,在settings.py的REST_FRAMEWORK中定义DEFAULT_THROTTLE_CLASSES (限流类)和 DEFAULT_THROTTLE_RATES(限流周期)
过滤与排序属性
- 过滤
- 安装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选项定义