# 视图集
两个基本
```python
--ViewSet---
# 继承自 APIView, ViewSetMixin[路由扩展类]
# 请求: 方法
url(r'^books/$', views.BookViewSet.as_view({'get': 'list', 'post': 'create'}))
# 自定义方法[/def/$]
url(r'^books/last/$', views.BookViewSet.as_view({'get': 'last'}))
# 正则参数匹配[/(?P<>..)/]
url(r'^books/(?P<pk>\d+)/show/$', views.BookViewSet.as_view({'get': 'show'}))
from rest_framework.viewsets import ViewSet
from Books.models import BookInfo
from book.serializers import BookSerializer
from rest_framework.response import Response
class BookViewSet(ViewSet):
def list(self, request): # list --> 请求方法
books = BookInfo.objects.all()
ser = BookSerializer(books, many=True)
return Response(ser.data)
...
```
```python
--GenericViewSet--
# 继承自 GenericAPIView 和 ViewSet
url(r'^books/last/$', views.BookGenericViewSet.as_view({'get': 'last'}))
from rest_framework.viewsets import ViewSet, GenericViewSet
from Books.models import BookInfo
from book.serializers import BookSerializer
from rest_framework.response import Response
class BookGenericViewSet(GenericViewSet):
serializer_class = BookSerializer
queryset = BookInfo.objects.all()
def list(self, request):
book = self.get_queryset() # 变形
ser = self.get_serializer(book, many=True) # 变形
return Response(ser.data)
...
```
两个拓展
```python
--ModelViewSet--
# 继承自 GenericViewSet 和 CreateModelMixin, RetrieveModelMixin, UpdateModelMixin,DestroyModelMixin, ListModelMixin
# ---> {'请求方式': '拓展类方法名'}
url(r'^books/last/$', views.BookModelViewSet.as_view({'get': 'retrieve'}))
# ---> '/(?P<>..)/新方法名'
url(r'^books/(?P<pk>\d+)/show/$', views.BookViewSet.as_view({'get': 'show'}))
from rest_framework.viewsets import ViewSet, GenericViewSet
from Books.models import BookInfo
from book.serializers import BookSerializer
from rest_framework.response import Response
class BookModelViewSet(ModelViewSet):
serializer_class = BookSerializer
queryset = BookInfo.objects.all()
class RetrieveModelMixin(object):
def retrieve(self, request, *args, **kwargs): # url() ---> def retrieve()
....
....
```
```python
--ReadOnlyModelViewSet--
# 继承自 GenericViewSet 和 RetrieveModelMixin, ListModelMixin
代码基本一致(略)
...
```
action属性
```python
from rest_framework.viewsets import ModelViewSet
class BookModelViewSet(ModelViewSet):
# serializer_class = None
queryset = BookInfo.objects.all()
def get_serializer_class(self): # 重写 --> GenericViewSet --> serializer按需分配
if self.action == 'list':
return BookSerializer
elif self.action = 'create': # action 为 视图集参数, 不继承无法使用
return BookSerializer1
else:
return BookSerializer2
...
...
```
自动生成路由
```python
from rest_framework.routers import SimpleRouter
urlpatterns = []
route = SimpleRouter() # 创建对象
route.register('books',views.BookModelViewSet, base_name='book') # 注册
urls = route.urls # 获取路径
urlpatterns += urls # 添加
```
action装饰器
```python
# 注册自己书写的程序(默认以外:get), 用装饰器
from rest_framework.decorators import action
@action(methods=['get'], detail=True) # 请求方式, detail --> True匹配路由参数pk
def show(self, request, pk):
book = self.get_object()
ser = self.get_serializer(book,)
return Response(ser.data)
@action(methods=['put', 'post'], detail=False) # 请求方式, detail-->False不匹配
def show(self, request):
book = self.get_object()
ser = self.get_serializer(book)
return Response(ser.data)
```
两个路由类的区别
```python
SimpleRouter
DefaultRouter(SimpleRouter) # 新增 首页匹配 规则 --> 127.0.0.1:8000
route = DefaultRouter()
...
...
```
视图与视图集应用场景分析
```python
局限: 视图集
# -- 接收表单, Json 数据 --- 其他数据不支持不适用
# -- 超出需求范围 -- 浪费资源不适用
'''
多功能, 多路由需求, 最佳选择
'''
```
# 其他功能的使用
认证
```python
---全局配置---
...
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication', # 基本认证
'rest_framework.authentication.SessionAuthentication' # session认证
)
}
---局部配置---
class BookModelViewSet(ModelViewSet):
...
authentication_classes = (BasicAuthentication, SessionAuthentication)
```
权限
```python
# AllowAny 允许所有用户
# IsAuthenticated 仅通过认证的用户
# IsAdminUser 仅管理员用户
# IsAuthenticatedOrReadOnly 认证的用户可以完全操作,否则只能get读取
---全局配置---
...
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated'
)
}
---局部配置---
class BookModelViewSet(ModelViewSet):
...
permission_classes = (IsAuthenticated,)
```
限流
```python
# AnonRateThrottle 限制所有匿名未认证用户
# UserRateThrottle 限制认证用户
# ScopedRateThrottle 限制用户对于每个视图的访问频次
---全局配置---
...
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle', # 游客
'rest_framework.throttling.UserRateThrottle' # 认证用户
),
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day', # day, hour, minute, second
'user': '1000/day'
}
}
---局部配置---
class BookModelViewSet(ModelViewSet):
...
throttle_classes = (UserRateThrottle,)
# ????
throttle_scope = 'contacts'
```
过滤
```python
# 增强工具
pip install django-filter
# 注册
INSTALLED_APPS = [
'django_filters',
]
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
# 使用
class BookListView(ListAPIView): # 继承 ModelListMixin 才能用 filter_fields
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
filter_fields = ('btitle', 'bread') # 加入对应字段
```
排序
```python
from rest_framework.filters import OrderingFilter
class BookListView(ListAPIView): # ModelListMixin
filter_backends = [OrderingFilter, DjangoFilterBackend]
ordering_fields = ('bread',)
```
分页
```python
PageNumberPagination
# page_size 每页数目
# page_query_param 前端发送的页数关键字名,默认为"page"
# page_size_query_param 前端发送的每页数目关键字名,默认为None
# max_page_size 前端最多能设置的每页数量
---全局配置---
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100 # 每页数目
}
---局部配置---
from rest_framework.pagination import PageNumberPagination
class PageNum(PageNumberPagination):
page_size_query_param = 'page_size' # = '?参数名=', 控制页数
max_page_size = 5 # 每页最大数
class BookListView(ListAPIView):
pagination_class = PageNum # 需要引入分页器, None为关闭
```
```python
LimitOffsetPagination
# default_limit 默认限制,默认值与PAGE_SIZE设置一致
# limit_query_param limit参数名,默认'limit'
# offset_query_param offset参数名,默认'offset'
# max_limit 最大limit限制,默认None
---全局配置---
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 100 # 每页数目
}
---局部配置---
from rest_framework.pagination import LimitOffsetPagination
class LimitPageNum(PageNumberPagination): # /?offset=3&limit=2
limit_query_param = 'limit'
offset_query_param = 'offset'
max_limit = 10
default_limit = 100 # 默认值 = PAGE_SIZE
class BookListView(ListAPIView):
pagination_class = LimitPageNum # 需要引入分页器, None为关闭
```
异常处理
```python
---全局配置---
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'rest_framework.views.custom_exception_handler', # '方法路径'
}
--定义--
from rest_framework.views import exception_handler
from rest_framework import status
from django.db import DatabaseError
def custom_exception_handler(exc, context):
response = exception_handler(exc, context) # 先调用drf默认方法 --> 标准错误响应对象
# 自定义的异常处理
if response is not None:
response.data['status_code'] = response.status_code
return response
```
自动生成接口文档
```python
# 接口API文档, 可以自动生成, 由于文档是程序完工后生成的, 而工作需要先获取API文档才能开展, 故不常用此功能
--安装--
pip install coreapi
--路径--
from rest_framework.documentation import include_docs_urls
urlpatterns = [
url(r'^docs/', include_docs_urls(title='My API title'))
]
--可视化地址--
127.0.0.1:8000/docs
--描述写法--
def list():
"""
方法描述
"""
class BookView():
"""
作用描述
"""
bread = models.IntegerField(....., help_text='阅读量') # help_text 关键字
class BookReadSerializer(serializers.ModelSerializer):
class Meta:
model = BookInfo
fields = ('bread', )
extra_kwargs = {
'bread': {
'required': True,
'help_text': '阅读量' # help_text 关键字
}
}
```
|
|