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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© gamadi 初级黑马   /  2019-6-20 15:21  /  1470 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

[TOC]

### rest_framework

------

- 优点:获取前端数据自动转换
- rest_framework中导入APIView的request和response对象不同:
  - request(自动进行数据解析)
    - .data   => {}     获取前端数据
    - .FILES
    - .query_params      获取查询集中的数据   即为原先的request.GET获取的数据
  - response
    - 不区分返回数据类型,可自动进行数据转换

------

#### APIView和GenericAPIView(两个基本类视图)

- APIView

  - 继承Django的View

  - 限流(访问次数的限制)

  - 权限(访问资源的权限)

  - 认证属性

  - ```python
    from rest_framework.authentication import SessionAuthentication
    from rest_framework.permissions import IsAuthenticated
    from rest_framework.generics import RetrieveAPIView
    from rest_framework.throttling import UserRateThrottle
   
    class BookDetailView(RetrieveAPIView):
        queryset = BookInfo.objects.all()
        serializer_class = BookInfoSerializer
        authentication_classes = [SessionAuthentication]   # 认证
        permission_classes = [IsAuthenticated]   # 权限
        throttle_classes = (UserRateThrottle,)   # 限流
    ```

  -

- GenericAPIView

  - 继承自APIView
  - 过滤属性---filter_backends
  - 分页---pagination_class
  - 指定查询集属性---queryset
    - 获取查询集合中的所有数据:def get_queryset()
    - 获取查询集中的单一数据:def get_object()---自动获取pk值,获取唯一对象
  - 指定序列化器属性---serializer_class  
    - 获取序列化器对象:def get_serializer()
    - 指定多个序列化器:def get_serializer_class()

------

#### 五个拓展类

- 相互之间是独立的,无继承关系
- 拓展类子类(多继承于五个拓展类)

***在查询对象不唯一时,要设置many=True***

- 拓展类配合GenericAPIView使用:因为拓展类重要调用GenericAPIView中的方法
  - 在视图中的使用就可以调用

------

#### 视图集

视图集和视图区别:是否继承ViewSetMixin

- 基本视图集(两者之间方法的调用存在区别)
  - Viewset---继承自APIView和ViewSetMixin
  - GenricViewset---继承自GenricAPIView(可以使用get_queryset和get_serializer)
- 拓展视图集
  - ModelViewset
    - 继承自GenricViewset和五个拓展类
    - 就可以对功能进行封装
  - ReadOnlyModelViewset
    - 只能用于获取单一或全部的数据

1. ***自定义视图方法:url中as_view({'get':'list'})    进行方法的映射***
   - 使用查询集时,正则写在路由中间
   - http方法一条路由中最多出现一次
   - 对需要传pk值的方法,写入带有正则匹配的路由
   - 也可自定义新方法,实现新的功能
   - 拓展类中已经定义好的API方法:
     - get-单一-retrieve
     - put---update
     - delete---destroy
     - post---create

```python
#视图集路由匹配 viewset,继承自ViewSetMixin可以设置路由
    url(r'^books/$', view_set.BooksViewSet.as_view({'get':'list','post':'create'})),
    url(r'^books/last/$', view_set.BooksViewSet.as_view({'get':'last'})),
    url(r'^books/(?P<pk>\d+)/show/$', view_set.BooksViewSet.as_view({'get':'show'})),
```

```python
# GenericViewSet
    url(r'^books/$', view_set.BooksGenericViewSet.as_view({'get': 'list', 'post': 'create'})),
    url(r'^books/last/$', view_set.BooksGenericViewSet.as_view({'get': 'last'})),
    url(r'^books/(?P<pk>\d+)/show/$', view_set.BooksGenericViewSet.as_view({'get': 'show'})),
```

```python
# ModelViewSet
        url(r'^books/$', view_set.BooksModelViewSet.as_view({'get': 'list', 'post': 'create'})),
    url(r'^books/(?P<pk>\d+)/$', view_set.BooksModelViewSet.as_view({'get': 'retrieve','put':'update','delete':'destroy'})),
    url(r'^books/(?P<pk>\d+)/show/$', view_set.BooksModelViewSet.as_view({'get': 'show'})),
```

------

#### action

***对方法指定序列化器***

- get_serializer_class返回序列化器,则可以改写父类:GenricAPIView中的此方法,规定返回的序列化器

```python
def get_serializer_class(self): # 此方法写了以后对于指定的serializer__class就是去效用
    if self.action == 'list':  # action动作,针对于路由映射
        return BookSerializer
    else self.action == 'create':
        return BookSerilizer1
```



------

#### 自动生成路由

***只有使用视图集才能使用路由映射,self.action,自动生成路由集***

##### SimpleRouter

```python
from rest_framework.routers import SimpleRouter
route = SimpleRouter()  # 路由实例化
# 参数第一参数是路径第一项,第二参数表对应视图,第三参数表示路由名称
route.register('books_drf', view_set.BooksModelViewSet, base_name='book')
urlpatterns += route.urls
```

**在路由匹配规则当中已经知道各个请求的对应关系,只会对已经封装好的拓展类方法进行匹配**

- 对自定义的方法

  

##### action装饰器的使用

```python
@action(methods=['get','post','put'],detail=True) # 指定对应的请求方式(可以指定多个请求),detail=True效果体现在生成正则匹配,用于接收参数(pk值)
def show(self,request,pk):
    book = self.get_object()
    ser = self.get_serializer(book)
    return Response(ser.data)
```



##### DefaultRouter

和SimpleRouter相比,DefaultRouter可以自动生成***首页***的匹配,一般用DefaultRouter

------

#### 视图和视图集的使用场景分析

- 视图集:
  - 优点:
    - 对数据资源进行**增删改查**进行**多个功能**的实现(如:美多商城收货地址)
  - 局限性:
    - 数据获取:只能获取请求体中的**表单和json数据**(request.data)
    - 功能溢出,浪费资源空间(如:注册功能只需要进行保存)
- 基本类视图
  - 实现其他功能

------

#### 认证和权限

##### 全局使用

***全局配置对所有的视图均生效***

- 认证配置:基本认证、session认证
- **提供的配置**
  - AllowAny 允许所有用户
  - IsAuthenticated 仅通过认证的用户
  - IsAdminUser 仅管理员用户
  - IsAuthenticatedOrReadOnly 认证的用户可以完全操作,否则只能get读取

```python
REST_FRAMEWORK = {
    # 认证配置
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.BasicAuthentication',   # 基本认证
        'rest_framework.authentication.SessionAuthentication',  # session认证
    ),

    # 权限配置
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated', # 此处对用户的权限进行限制,对全局生效
    )
```

##### 局部使用

- 权限和认证属性的使用:

  - ```python
    from rest_framework.authentication import SessionAuthentication
    from rest_framework.permissions import IsAuthenticated
    from rest_framework.generics import RetrieveAPIView
   
    class BookDetailView(RetrieveAPIView):
        queryset = BookInfo.objects.all()
        serializer_class = BookInfoSerializer
        authentication_classes = [SessionAuthentication]   # 局部指定认证
        permission_classes = [IsAuthenticated]    # 局部指定权限
    ```

  - 在对应的视图中定义属性,只在当前视图中生效

------

#### 限流的使用

- 全局限流

```python
  # 用户划分限流
    #'DEFAULT_THROTTLE_CLASSES': (
        #'rest_framework.throttling.AnonRateThrottle',
        #'rest_framework.throttling.UserRateThrottle'
    #),
    # 指定不同用户访问次数
    'DEFAULT_THROTTLE_RATES': {
        'anon': '3/day',    # 未登录用户访问次数的限制
        'user': '2/day'            #  已认证用户访问次数
    },
```

- 局部限流

  - ```python
    from rest_framework.throttling import UserRateThrottle
    from rest_framework.views import APIView
   
    class ExampleView(APIView):
        throttle_classes = (UserRateThrottle,)
        ...
    ```

  - 给限流属性取名,在配置中自定义

```python
class ContactListView(APIView):
    throttle_scope = 'contacts'
    ...

class ContactDetailView(APIView):
    throttle_scope = 'contacts'
    ...

class UploadView(APIView):
    throttle_scope = 'uploads'
    ...
```

```python
# 配置文件中
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.ScopedRateThrottle',
    ),
    'DEFAULT_THROTTLE_RATES': {
        'contacts': '1000/day',  # 一天中访问1000次
        'uploads': '20/day'
    }
}
```

------

#### filter过滤

- 使用限制:
  - 查询拓展类中存在过滤功能(查询时使用)
  - 基本视图中直接获取查询集的无法进行过滤

1. 安装过滤模块

   ```python
   pip insall django-filter
   ```

   

2. 注册,指定过滤

   ```python
   INSTALLED_APPS = [
       ...
       'django_filters',  # 需要注册应用,
   ]
   
   REST_FRAMEWORK = {
       'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
   }
   ```

3. 过滤字段指定

   ```python
   class BookListView(ListAPIView):
       queryset = BookInfo.objects.all()
       serializer_class = BookInfoSerializer
       filter_fields = ('btitle', 'bread') # 支持哪些字段的过滤,以查询字符串的方式进行过滤
   
   # 127.0.0.1:8000/books/?btitle=西游记
   ```

------

#### 排序的使用

- 进行数据返回的时候,展示数据按照字段的大小顺序进行排序过滤
- 同样只能在**查询(List)拓展类**中试用

```python
class BookListView(ListAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer
    filter_backends = [OrderingFilter]
    ordering_fields = ('id', 'bread', 'bpub_date')

# 127.0.0.1:8000/books/?ordering=-bread
```

------

#### 分页的使用

REST framework提供了分页的支持。

我们可以在配置文件中设置全局的分页方式,如:

```python
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS':  'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 100  # 每页数目
}
```

也可通过自定义Pagination类,来为视图添加不同分页行为。在视图中通过`pagination_clas`属性来指明。

```python
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
```

**注意:如果在视图内关闭分页功能,只需在视图内设置**

```python
pagination_class = None
```

## 可选分页器

1) **PageNumberPagination**

前端访问网址形式:

```http
GET  http://api.example.org/books/?page=4
```

可以在子类中定义的属性:

- page_size 每页数目
- page_query_param 前端发送的页数关键字名,默认为"page"
- page_size_query_param 前端发送的每页数目关键字名,默认为None
- max_page_size 前端最多能设置的每页数量

```python
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
```

2)**LimitOffsetPagination**

前端访问网址形式:

```http
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

```python
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
```

1 个回复

倒序浏览
hello 麻瓜
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马