文章目录
节流
节流类似于权限,⽤于控制客户端可以对API发出的请求的速率。
自定义类
继承自SimpleRateThrottle,要在里面设置rate和重写get_cache_key(self, request, view)
App\MyThrottle.py
from rest_framework.throttling import SimpleRateThrottle
class MyThrottle(SimpleRateThrottle):
rate = '5/m' # 请求次数/时间段 (s,m,h,d)
def get_cache_key(self, request, view):
#根据用户ID,登录不限制,不登录限制每分钟5次
if request.user and request.user.id:
return None # 返回None,没有次数限制
else:
return 1 # 未登录用户
局部限制
views.py
class UserInfoView(GenericAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
# 局部认证,只针对当前类
authentication_classes = (MyAuthentaion,)
# 节流
throttle_classes = (MyThrottle,)
lookup_field = 'pk'
def get(self,request,pk):
obj = self.get_object() # 获取对象
us = UserSerializer(instance=obj) # 序列化
return Response(us.data)
上述视图实现了对登陆后(通过认证)的用户无访问限制,对未登录用户/token过期用户 限制为访问每分钟5次。
全局限制
使用自定义节流类
- 在自定义节流类中设置一个scope。
scope = 'MyThrottle'
- setting设置
REST_FRAMEWORK = {
# 对所有接口限制
'DEFAULT_THROTTLE_CLASSES': ['App.MyThrottle.MyThrottle'],
}
使用DRF提供的节流类
- setting设置
REST_FRAMEWORK = {
# 对所有接口限制
'DEFAULT_THROTTLE_CLASSES': ['rest_framework.throttling.AnonRateThrottle'],
'DEFAULT_THROTTLE_RATES': {
'anon': '2/day',# 匿名用户
},
}
可选节流类
- AnonRateThrottle
限制所有匿名未认证⽤户,使⽤IP区分⽤户。
使⽤ DEFAULT_THROTTLE_RATES[‘anon’] 来设置频次 - UserRateThrottle
限制认证⽤户,使⽤User id 来区分。
使⽤ DEFAULT_THROTTLE_RATES[‘user’] 来设置频次 - ScopedRateThrottle
限制⽤户对于每个视图的访问频次,使⽤ip或user id。
分页
系统提供的可选分页器
PageNumberPagination
- 前端访问形式
GET http://api.example.org/books/?page=4
。 - 可定义属性
- page_size 每⻚数⽬
- page_query_param 前端发送的⻚数关键字名,默认为"page"
- page_size_query_param 前端发送的每⻚数⽬关键字名,默认为None
- max_page_size 前端最多能设置的每⻚数量
LimitOffsetPagination
- 前端访问形式
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
全局分页
在setting.py里进行设置。
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS':
'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10 # 每⻚数⽬
}
http://127.0.0.1:8000/book/?page=2&page_size=3
自定义类
自定义分页要重写get_paginated_response(self, data)方法,
class BookListPager(PageNumberPagination):
page_size = 3 # 每页3条记录
page_size_query_param = 'page_size' # 每页记录数的参数名字
# 自定义分页形式
def get_paginated_response(self, data):
return Response(OrderedDict([
('count', self.page.paginator.count),
('page_range', list(self.page.paginator.page_range)), # 页码范围
('has_next', self.page.has_next()),
('has_prious', self.page.has_previous()),
('next_page_number', self.page.next_page_number()),
('results', data)
]))
针对视图写分页
views.py
class BookListView(GenericAPIView):
queryset = Bookinfo.objects.all()
serializer_class = BookinfoSerializer
pagination_class = BookListPager
def get(self,request,*args,**kwargs):
# 过滤结果集
queryset = self.filter_queryset(self.get_queryset())
# 系统实现分页,获取分页对象
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
# page为None,不分页,返回所有数据
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
或者是直接继承ListAPIView,父类已经写好相关的方法。
class BookListView(ListAPIView):
queryset = Bookinfo.objects.all()
serializer_class = BookinfoSerializer
pagination_class = BookListPager
过滤
- 使用django-filter 第三方应用
- setting配置
INSTALLED_APPS = [
...
'django_filters', # 需要注册应⽤,
]
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
简单配置
class BooksView(ListAPIView):
queryset = Bookinfo.objects.all()
serializer_class = BookinfoSerializer
# 过滤字段
filter_fields = ('btitle', 'bread')
- 这种方式只能使用等于,如果要有大于,小于,包含等过滤,需要自定义过滤器
自定义过滤器
- 使用条件字典
App\MyFilters.py
class BookFilter(filters.FilterSet):
class Meta:
model = Bookinfo
fields = {
# 运算符和ORM中一样
# http://127.0.0.1:8000/list/?btitle__icontains=%E4%BD%99
'btitle': ['icontains', 'startswith', 'iendswith'], # 不区分大小写的包含,开头,结尾
'bcomment': ['lt', 'gt'], #
'bread': ['lte', 'gte', 'in'],
'bpub_date': ['exact', 'gt', 'year__lt', 'year__gt'],
'bimage': ['isnull']
}
views.py
class BooksView(ListAPIView):
queryset = Bookinfo.objects.all()
serializer_class = BookinfoSerializer
filter_class = BookFilter
- 自定义查询方法
App\MyFilters.py
class BookFilter(filters.FilterSet):
class Meta:
model = Bookinfo
fields = {
# 运算符和ORM中一样
# http://127.0.0.1:8000/list/?btitle__icontains=%E4%BD%99
'btitle': ['icontains', 'startswith', 'iendswith'], # 不区分大小写的包含,开头,结尾
'bcomment': ['lt', 'gt'], #
'bread': ['lte', 'gte', 'in'],
'bpub_date': ['exact', 'gt', 'year__lt', 'year__gt'],
'bimage': ['isnull']
}
# 查询字段名不要求和模型中一模一样
# field_name 模型中的字段名
# method 查询方法
# http://127.0.0.1:9090/list/?comment=50
comment = filters.NumberFilter(field_name='bcomment', method='find_comment')
def find_comment(self, queryset, name, value):
return queryset.filter(bcomment__lt=value)
生成接口文档
- 安装依赖
pip install coreapi
- setting.py
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS':
'rest_framework.schemas.coreapi.AutoSchema'
}
- 总路由中添加路径
from rest_framework.documentation import include_docs_urls
urlpatterns = [
...
path('docs/', include_docs_urls(title='My API title'))
]
- 视图设置
文档描述说明定义
# 视图
class BookListCreateView(generics.ListCreateAPIView):
"""
get:
返回所有图书信息.
post:
新建图书.
"""
# 视图集
class BookInfoViewSet(mixins.ListModelMixin,
mixins.RetrieveModelMixin, GenericViewSet):
"""
list:
返回图书列表数据
retrieve:
返回图书详情数据
latest:
返回最新的图书数据
read:
修改图书的阅读量
"""
- 访问接口文档网页
127.0.0.1:8000/docs/