A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© A181202875 初级黑马   /  2019-6-21 19:29  /  1212 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

# 视图集

两个基本

```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 关键字
            }
        }

```

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马