1 频率类

# 某个接口,限制访问频率----》可以根据IP,用户id
# 频率类的编写
-第一步:写一个类,继承SimpleRateThrottle
   -第二步:重写get_cache_key方法
   -第三步:返回什么,就以什么做限制
   -第四步:写一个类属性
  -scope = '3_min'
   -第五步:配置文件中配置
  REST_FRAMEWORK = {
           # 频率类中scope对应的值
           '3_min':'3/m'   # 数字/s m h d
      }
       
  -第六步:局部和全局使用
局部用:视图类中
  class BookView(APIView):
  throttle_classes = [IPThrottle, ]
   全局用:配置文件
  REST_FRAMEWORK = {
           "DEFAULT_THROTTLE_RATES": {
               # 频率类中scope对应的值
               '3_min': '3/m'  # 数字/s m h d
          },
           'DEFAULT_THROTTLE_CLASSES':['app01.throttling.IPThrottle',]
      }

1.1 使用

频率类

class IPThrottle(SimpleRateThrottle):
   # 写一个类属性,字符串
   scope = '3_min'
   def get_cache_key(self, request, view):
       # return 什么就一什么做限制, 返回ip   返回用户id
       return request.META.get('REMOTE_ADDR')
       # return request.user.id # 返回用户id

视图类

class BookView(APIView):
   throttle_classes = [IPThrottle, ]

   def get(self, request):
       return Response('ok')

   def throttled(self, request, wait):
       from rest_framework.exceptions import Throttled
       class MyThrottled(Throttled):
           default_detail = '超限制了'
           extra_detail_singular = '还有 {wait} 描述.'
           extra_detail_plural = '出了 {wait} 秒.'

       raise MyThrottled(wait)

配置文件

REST_FRAMEWORK = {
   "DEFAULT_THROTTLE_RATES": {
       # 频率类中scope对应的值
       '3_min': '3/m',  # 数字/s m h d
       'anon':'4/h',
       'user':'5/m'
  },
   'DEFAULT_THROTTLE_CLASSES':['app01.throttling.IPThrottle',]

}

 

2 drf内置认证类,权限类,频率类

# 内置的认证---》跟咱们项目都补贴和,咱们不用,咱们自己根据自己的规则写
-SessionAuthentication:之前老的session认证登录方式用,后期都不用了
   -BasicAuthentication :基本认证方式,咱们不用
   -TokenAuthentication :使用token认证方式,有用,但是咱们也是自己写的
   
   
# 内置的权限类
-IsAdminUser :校验是不是auth的超级管理员权限
   -IsAuthenticated:后面会用到,验证用户是否登录了,登录了才有权限,没登录就没有权限
   -IsAuthenticatedOrReadOnly:知道有这个东西即可
   
# 内置的频率类
-UserRateThrottle :限制登录用户的频率,需要配置配置文件
   -AnonRateThrottle:登录用户不限制,未登录用户限制,需要配置配置文件

 

3 认证类源码分析

 

####### 不要无脑按住ctrl建点击查找,因为方法,属性的查找顺序是按照 mro列表查找顺序来的

# 研究第一个点:三大认证的执行顺序---》入口---》APIView的dispathc----》三大认证
-dispatch中第 497--》self.initial(request, *args, **kwargs)
   -self是谁?self是个对象,是谁的对象? 是视图类的对象---》BookView这些视图类
   -APIView的initial方法的第414行
       self.perform_authentication(request)  # 认证
       self.check_permissions(request)     # 权限
       self.check_throttles(request)      # 频率
       
       
       
# 为什么写了认证类,配置在视图类上,就会走认证?---》入口-->self.perform_authentication(request)
-第一步:self.perform_authentication源码
   def perform_authentication(self, request):
    request.user
    -第二步:新的request类中 user(属性?方法?)
  from rest_framework.request import Request
        @property
       def user(self):
           if not hasattr(self, '_user'):
               with wrap_attributeerrors():
                   self._authenticate()  # 最开始,是没有_user的,执行这句
           return self._user
   -第三步:self._authenticate()  --》self是Request的对象---》Request的_authenticate方法
   def _authenticate(self):
           # authenticator配置的认证类的对象
           for authenticator in self.authenticators: # 你配置在视图类上authentication_classes = [你写的认证类,]----》[你写的认证类(),你写的认证类2()]
               try:
                   # 调用认证类对象的authenticate方法,传了几个?2个,一个认证类自己,一个是self:Request类的对象
                   user_auth_tuple = authenticator.authenticate(self)
               except exceptions.APIException: # 抛的是AuthenticationFailed,捕获的是APIException
                   self._not_authenticated()
                   raise

               if user_auth_tuple is not None:
                   self._authenticator = authenticator
                   # 如果返回了两个值,第一个值给了request.user,第二个值给了request.auth
                   self.user, self.auth = user_auth_tuple
                   return

-第四步: self.authenticators到底是啥---》你配置在视图类上authentication_classes = [你写的认证类,]----》[你写的认证类(),你写的认证类2()]
  -Reqeust这个类实例化的时候,传入的,如果不传就是空元组
       -找Request的实例化---》dispatch中包装了新的Request
      -request = self.initialize_request(request, *args, **kwargs)
           -authenticators=self.get_authenticators(),
           
       -APIView中get_authenticators---》268行
         def get_authenticators(self):
            # self.authentication_classes配在视图类上的认证类列表---》认证类对象列表
      return [auth() for auth in self.authentication_classes]

 

4 排序

# 排序功能接口只针对于:获取所有接口

# 继承了GenericAPIView的视图类,只要加入,两个类属性
class BookView(GenericViewSet, ListModelMixin):
   serializer_class = BookSerializer
   queryset = Book.objects.all()

   filter_backends = [OrderingFilter, ]
   ordering_fields = ['price','id' ]
# 访问的时候
http://127.0.0.1:8000/api/v1/books?ordering=price  # 按price升序
http://127.0.0.1:8000/api/v1/books?ordering=-price # 按price降序
http://127.0.0.1:8000/api/v1/books?ordering=price,id # 先按价格升序排,价格一样,再按id升序排

 

5 过滤

#  查询名字为银瓶梅的所有图书:获取所有接口

# 内置的过滤使用---》不能指定查询那个字段,模糊查询
-继承了GenericAPIView的视图类,只要加入,两个类属性
   class BookView(GenericViewSet, ListModelMixin):
       serializer_class = BookSerializer
       queryset = Book.objects.all()

       filter_backends = [SearchFilter,]
       search_fields=['name','price']  # 按name或price过滤
-使用
       http://127.0.0.1:8000/api/v1/books?search=银瓶梅
       # search= xx ----》具体查询是 name like xx or price like xx
       
# 我们想http://127.0.0.1:8000/api/v1/books?name=银瓶梅&price=12---》第三方django-filter
-安装:pip3 install django-filter
   
   -继承了GenericAPIView的视图类,只要加入,两个类属性
        from django_filters.rest_framework import DjangoFilterBackend
        class BookView(GenericViewSet, ListModelMixin):
           serializer_class = BookSerializer
           queryset = Book.objects.all()

           filter_backends = [DjangoFilterBackend, ]
           filter_fields = ['name', 'price']
   
   -使用
   http://127.0.0.1:8000/api/v1/books?name=银瓶梅&price=11

   
   
 # 自定义过滤器---》完成更多查询操作
-写一个类,继承BaseFilterBackend
   -重写filter_queryset方法
   -配置在视图类中
   from .throttling import FilterName
   class BookView(GenericViewSet, ListModelMixin):
       serializer_class = BookSerializer
       queryset = Book.objects.all()

       filter_backends = [FilterName, ]
       
       
       
 # 既有过滤又有排序
   class BookView(GenericViewSet, ListModelMixin):
       serializer_class = BookSerializer
       queryset = Book.objects.all()
       filter_backends = [FilterName, OrderingFilter]
       ordering_fields = ['price', ]
       
# 源码分析,为什么这么配置就生效

-GenericAPIView的方法
   def filter_queryset(self, queryset):
       for backend in list(self.filter_backends):
           queryset = backend().filter_queryset(self.request, queryset, self)
       return queryset




 

 

 

回顾

# http回顾
-http 请求:特点
    -1 http基于tcp之上的协议---》tcp处于 osi七层的传输层  http是处于应用层
    -2 基于请求响应  必须是客户端发起请求,服务端响应,不能服务端主动推送消息
    -3 无状态,无连接  cookie和session
   -http协议有版本
  -0.9  1.1  2.x:多路复用   3.x
   -http分请求协议和响应协议
  -请求协议
      -请求首行:请求方式,请求地址(get地址中数据),协议版本
           -请求头:key:value  客户端类型,客户端ip地址,请求编码,cookie。。。。
           -请求体:所谓的body体,post,put请求真正携带的数据
          -urlencoded:  name=lqz&age=19&gender=male
               -json :   {"name":"lqz","age":19,"gender":"male"}
               -form-data: 两部分:数据部分,文件部分中间用  -----------分割
  -响应协议
      -响应首行:协议版本,响应状态码,响应状态短语
           -响应头:响应编码格式,cookie。。。
           -响应体:html,json,xml。。。。
   
   
   
# websocket协议 应用层协议
-服务端主动向客户端推送的情况,使用websocket
   
# http请求 轮询
# http请求 长轮询 :发过去,等一会,再回来
# websocket 协议主动推送


 posted on 2022-06-25 18:00  鳗鱼的春天  阅读(150)  评论(0编辑  收藏  举报