一、Authentication:认证
可在配置文件中设置全局认证或类视图中局部定义。通常默认使用的是SessionAuthentication
,BasicAuthentication
两种认证,
- 全局设置
在settings配置文件中:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication', # 基本认证
'rest_framework.authentication.SessionAuthentication', # session认证
)
}
- 类视图局部设置:
使用authentication_classes
属性来设置
只能在继承于APIView的类及其扩展类的视图类中使用
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.views import APIView
class ExampleView(APIView):
authentication_classes = (SessionAuthentication, BasicAuthentication)
...
注意:Authentication身份验证本身并不会禁止传入请求,它只是标识请求所使用的凭据,需要配合权限认证Permissions一起使用才有限制作用。
二、Permissions:权限
权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。
- 在执行视图的dispatch()方法前,会先进行视图访问权限的判断
- 在通过get_object()获取具体对象时,会进行对象访问权限的判断
可以进行全局设置,不过一般不会这么操作,而是指定视图类来限制。
- 全局设置
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
- 类视图局部设置:
使用permission_classes
属性来设置
只能在继承于APIView的类及其扩展类的视图类中使用
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
class ExampleView(APIView):
permission_classes = (IsAuthenticated,)
...
- 提供的常用权限
权限 | 功能 |
---|---|
AllowAny | 允许所有用户 |
IsAuthenticated | 仅通过认证的用户 |
IsAdminUser | 仅管理员用户 |
IsAuthenticatedOrReadOnly | 认证的用户可以完全操作,未通过认证的用户只能读取操作 |
也可以通过重写BasePermission自定义权限。
三、Throttling:限流
可设置限制对接口的访问频次,防止恶意高频访问,降低服务器的压力。
- 全局设置
可以在配置文件中,使用DEFAULT_THROTTLE_CLASSES
和 DEFAULT_THROTTLE_RATES
设置限流类型、访问频次进行全局配置。
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
),
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/day'
}
}
- 局部设置
在类视图中指定throttle_classes
属性,设置限流对象,而具体的对应的限制频次仍在settings中进行全局配置。
from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView
class ExampleView(APIView):
throttle_classes = (UserRateThrottle,)
...
- 限流类功能及频率设定方法
限流类名 | 限制对象 | 限定频次设置 |
---|---|---|
AnonRateThrottle | 限制所有匿名未认证用户,使用IP区分用户 | anon |
UserRateThrottle | 限制认证用户,使用User id 来区分 | user |
ScopedRateThrottle | 限制用户对于每个视图的访问频次,使用ip或user id | 必须先在视图类中设定属性throttle_scope = 限制名 |
- 使用
ScopedRateThrottle
示例:
现在视图类中定义throttle_scope
属性,则速率限定的字段为设置的属性。
class ContactDetailView(APIView):
throttle_scope = 'contacts'
...
class UploadView(APIView):
throttle_scope = 'uploads'
...
DEFAULT_THROTTLE_RATES
使用上述定义的属性字段。
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.ScopedRateThrottle',
),
'DEFAULT_THROTTLE_RATES': {
'contacts': '1000/day',
'uploads': '20/day'
}
}
四、Filtering:过滤
对于列表数据可能需要根据字段进行过滤,我们可以通过添加django-fitlter扩展来增强支持。
使用Filtering可实现对请求url中?
后的查询字符串参数进行解析和过滤。
- 安装
django-filter
包
pip insall django-filter
- 配置过滤器
在配置文件中添加:
# 注册应用
INSTALLED_APPS = [
...
'django_filters',
]
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
),
}
- 指定过滤字段
需要注意的是,过滤功能只能在ListAPIView、ListModelMixin中使用,也就是说只能用在获取全部数据的操作中。
在类视图中添加filter_fields
属性,指定可以过滤的字段
class BookListView(ListAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
filter_fields = ('btitle', 'bread')
请求URL路径示例:
127.0.0.1:8000/books/?btitle=天龙八部
# 返回所有图书中标题为"天龙八部"的数据
在该视图类中定义的filter_fields = ('btitle', 'bread')
指过滤的字段指定为元祖中包括的两个字段,及前端访问的URL中,只匹配btitle
、 bread
两个查询字符串内容并返回。
五、OrderingFilter:排序过滤
OrderingFilter是带有排序功能的过滤器,和Filtering过滤器相同的是,它也只能在继承了ListAPIView
或ListModelMixin
的视图类中使用。
同时,在一个视图类中,Filtering与OrderingFilter只能二选一使用。
- 配置过滤器
在Filtering配置时已经完成配置文件配置。 - 使用方法
REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。
-
ordering_fields
包含内容为前端可以传递的ordering参数。 -
ordering
指定按该字段进行默认排序(当前端未传递ordering参数时)
class BookListView(ListAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
# filter_backends指定使用OrderingFilter还是Filtering,二者只能同时用其一
filter_backends = [OrderingFilter]
# 指定允许前端传递的查询字符串ording字段
ordering_fields = ('id', 'bread', 'bpub_date')
# 指定默认的排序字段
ordering = ("id")
请求URL路径示例:
127.0.0.1:8000/books/?ordering=-bread
# 返回所有图书并按阅读量降序排序
还可指定多字段排序:
127.0.0.1:8000/books/?ordering=-bread,-bpub_data
# 先按阅读量降序排序,阅读量相同的则按发布时间降序排序。
六、Pagination:分页
(一)使用PageNumberPagination分页
- 全局设置
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100 # 每页数目
}
- 局部设置
通过继承并自定义PageNumberPagination类,为视图添加不同分页行为。
class LargeResultsSetPagination(PageNumberPagination):
# 每页最大显示数量
page_size = 1000
# 指定前端查询第几页的关键字
page_query_param = 'page'
# 指定前端控制每页显示数量的关键字,默认为None不可控制
page_size_query_param = 'page_size'
# 每页最大显示数量限制,仅在设置了page_size_query_param时有效
max_page_size = 10000
然后在类视图下通过pagination_class
属性来指明该类视图下的分页设置。
class BookDetailView(ListAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
# 指明使用的pagination_class分页类
pagination_class = LargeResultsSetPagination
若需在视图内关闭分页功能,只需如下设置:
pagination_class = None
- PageNumberPagination类可定义属性
-
page_size
:每页数目 -
page_query_param
:前端发送的页数关键字名,默认为"page" -
page_size_query_param
:前端发送的每页数目关键字名,默认为None -
max_page_size
:前端最多能设置的每页数量
前端请求示例:请求第一页,每页显示数量为2。
127.0.0.1/books/?page=1&page_size=2
(二)使用LimitOffsetPagination分页
与PageNumberPagination基本相似
- 全局设置
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 100 # 每页数目
}
- 局部设置
继承LimitOffsetPagination类并自定义分页规则,或直接导入该类使用其默认设置。
使用默认设置示例:
from rest_framework.pagination import LimitOffsetPagination
class BookListView(ListAPIView):
queryset = BookInfo.objects.all().order_by('id')
serializer_class = BookInfoSerializer
pagination_class = LimitOffsetPagination
- LimitOffsetPagination类可定义属性
-
default_limit
:默认限制值,默认值与PAGE_SIZE设置一致 -
limit_query_param
:limit参数名,默认'limit' -
offset_query_param
:offset参数名,默认'offset' -
max_limit
:最大limit限制,默认None
前端请求示例:查询偏移量3,限制长度为2的页面数据
127.0.0.1:8000/books/?offset=3&limit=2
自定义分页数据返回格式
在定义的分页器类中,重写get_paginated_response方法
class PageNum(PageNumberPagination):
# 每页最大显示数量
page_size = 20
# 指定前端查询第几页的关键字
page_query_param = 'page'
# 指定前端控制每页显示数量的关键字,默认为None不可控制
page_size_query_param = 'page_size'
# 每页最大显示数量限制,仅在设置了page_size_query_param时有效
max_page_size = 10000
#重写该方法,自定义返回结果格式
def get_paginated_response(self,data):
retrun Response({
'count':XXX,
'result':XXX,
......
})