自定义频率类
from rest_framework.throttling import BaseThrottle
import time
class MyThrottling(BaseThrottle):
user_record = {}
def __init__(self):
self.history = None
def allow_request(self, request, view):
ip = request.META.get('REMOTE_ADDR')
ctime = time.time()
if ip not in self.user_record:
self.user_record[ip] = [ctime]
return True
self.history = self.user_record.get(ip)
while self.history and ctime - self.history[-1] > 60:
self.history.pop()
if len(self.history) < 3:
self.history.insert(0, ctime)
return True
return False
def wait(self):
ctime = time.time()
return 60 - (ctime - self.history[-1])
频率功能源码分析
-源码里执行的频率类的allow_request,在SimpleRateThrottle中找allow_request
-116行
if self.rate is None:
1.到self.rate中
def __init__(self):
if not getattr(self, 'rate', None):
self.rate = self.get_rate()
self.num_requests, self.duration = self.parse_rate(self.rate)
-到self.get_rate()中
if not getattr(self, 'scope', None):
msg = ("You must set either `.scope` or `.rate` for '%s' throttle" %
self.__class__.__name__)
raise ImproperlyConfigured(msg)
try:
return self.THROTTLE_RATES[self.scope]
-到self.parse_rate中
def parse_rate(self, rate):
if rate is None:
return (None, None)
num, period = rate.split('/')
num_requests = int(num)
duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
return (num_requests, duration)
def allow_request(self, request, view):
if self.rate is None:
return True
self.key = self.get_cache_key(request, view)
if self.key is None:
return True
self.history = self.cache.get(self.key, [])
self.now = self.timer()
while self.history and self.history[-1] <= self.now - self.duration:
self.history.pop()
if len(self.history) >= self.num_requests:
return self.throttle_failure()
return self.throttle_success()
'写频率类只需要继承SimpleRateThrottle,重写get_cache_key方法,配置属性scope,在配置文件中配置即可'
分页功能
'查询所有的接口才需要分页'
1.分页后端写法是固定的,前端展示形式是不一样的
-PC端的分页是下一页点击
-app中的分页是下拉加载更多
2.drf中分页的使用
-写一个继承了drf的三个分页类之一的类
-重写某几个类属性
-把它配置在继承自GenericAPIView+ListModelMixin的子视图上
3.分页类
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
-PageNumberPagination
class YouPageNumberPagination(PageNumberPagination):
page_size = 2
page_query_param = 'page'
page_size_query_param = 'size'
max_page_size = 5
-LimitOffsetPagination
class YouPageNumberPagination(LimitOffsetPagination):
default_limit = 2
limit_query_param = 'limit'
offset_query_param = 'offset'
max_limit = 5
-CursorPagination
class YouPageNumberPagination(CursorPagination):
cursor_query_param = 'cursor'
page_size = 2
ordering = 'id'
4.局部使用
pagination_class = YouPageNumberPagination
5.如果是继承APIView,需要自己写
class BookView1(APIView):
def get(self, request):
qs = Book.objects.all()
page = MyPageNumberPagination()
res = page.paginate_queryset(qs, request)
ser = BookSerializer(instance=res,many=True)
return Response(ser.data)
排序功能
'查询所有才设计到排序,其他接口都不需要'
-必须是继承GenericAPIView+ListModelMixin的子视图类上
1.排序类使用
from rest_framework.filters import OrderingFilter
class BookView(ModelViewSet):
filter_backends = [OrderingFilter]
ordering_fields = ['price', 'id']
serializer_class = BookSerializer
queryset = Book.objects.all()
2.支持前端的访问形式
'先按price的降序排,在按id的升序排'
http://127.0.0.1:8000/books/?ordering=-price,id
3.如果是继承APIView,需要自己写,需要从请求地址中取出排序规则,自己排序
'price','-id'=reqeust.query_params.get('ordering').split(',')
qs = Book.objects.all().order_by('price','-id')
'分页好排序能一起使用,但是是先排序后分页'
4.分页和排序能一起用,但是是先排序后分页的
'先按price的降序排,在按id的升序排,查询第2页,每页显示2条'
http://127.0.0.1:8000/books/?page=2&size=2&ordering=-price,id
过滤功能
'查询所有才设计到过滤,其他接口都不需要'
1.过滤是restful规范中的一条,请求地址中带的过滤条件(分页、排序、过滤)统称为过滤
2.过滤类使用
from rest_framework.filters import SearchFilter
class BookView(ModelViewSet):
filter_backends = [SearchFilter]
search_fields = ['name', 'publish']
serializer_class = BookSerializer
queryset = Book.objects.all()
3.支持前端的访问形式
'只要name中或publish中有红都搜出来'
http://127.0.0.1:8000/books/?search=红
'内置过滤类只能通过search写条件,如果配置了多个字段,是or的条件'
作业
1 自定义频率类,写一遍
2 使用3种分页方式,实现对查询所有数据接口的分页
3 带排序,带按名字过滤
4 继承APIView,实现分页,返回格式跟之前一样
class BookView1(APIView):
def get(self, request):
qs = Book.objects.all()
page = MyPageNumberPagination()
res = page.paginate_queryset(qs, request)
ser = BookSerializer(instance=res,many=True)
return Response(ser.data)
2
-PageNumberPagination
class YouPageNumberPagination(PageNumberPagination):
page_size = 2
page_query_param = 'page'
page_size_query_param = 'size'
max_page_size = 5
-LimitOffsetPagination
class YouPageNumberPagination(LimitOffsetPagination):
default_limit = 2
limit_query_param = 'limit'
offset_query_param = 'offset'
max_limit = 5
-CursorPagination
class YouPageNumberPagination(CursorPagination):
cursor_query_param = 'cursor'
page_size = 2
ordering = 'id'
3
1.类的使用
from rest_framework.filters import OrderingFilter, SearchFilter
class BookView(ModelViewSet):
filter_backends = [OrderingFilter, SearchFilter]
ordering_fields = ['price', 'id']
search_fields = ['name']
serializer_class = BookSerializer
queryset = Book.objects.all()
2.支持前端访问形式
'获取name字段中有"西"的数据,在按price的降序排,最后按id的升序排'
http://127.0.0.1:8000/books/?ordering=-price,id&search=西
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现