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