权限类使用,频率类使用,认证源码分析, 权限源码分析,鸭子类型
1.权限类使用
-第一步:写一个类,继承BasePermission
-第二步:重写has_permission方法
-第三步:在方法中校验用户是否有权限(request.user就是当前登录用户)
-第四步:如果有权限,返回True,没有权限,返回False
-第五步:self.message 是给前端的提示信息
-第六步:局部使用,全局使用,局部禁用
用数字当做类型来判定1是超级管理员。。等等
from rest_framework.permissions import BasePermission class TypeUserPermission(BasePermission): def has_permission(self,request,view): if request.user.user_type == '1': return True else: return False
2.频率类使用
-第一步:写一个类:继承SimpleRateThrottle
-第二步:重写get_cache_key,返回唯一的字符串,会以这个字符串做频率限制
-第三步:写一个类属性scop='随意写',必须要跟配置文件对象
-第四步:配置文件中写
'DEFAULT_THROTTLE_RATES': {
'随意写': '3/m' # 3/h 3/s 3/d
}
-第五步:局部配置,全局配置,局部禁用
class OurThrottle(SimpleRateThrottle): scope = 'ss' def get_cache_key(self, request, view): return request.META.get('REMOTE_ADDR') class UserThrottling(BaseThrottle): dic = {} def __init__(self): self.history = None def allow_request(self, request, view): ip = request.META.get('REMOTE_ADDR') import time timer = time.time() print(timer) if ip not in self.dic: self.dic[ip] = [timer, ] return True self.history = self.dic.get(ip) print(self.history) while self.history and timer - self.history[-1] > 60: # while self.history and -timer + self.history[-1] < 60: self.history.pop() if len(self.history) < 3: self.history.insert(0, timer) # print(self.history) return True else: return False
3.认证源码分析
# 写个认证类,重写某个方法,配置在视图类上,就有认证了---》认证类加了,在视图类的方法中,request.user就是当前登录用户---》猜认证类的执行,是在在视图类的方法之前执行的 # 源码分析: -之前咱们读APIView的执行流程---》包装了新的request,执行了3大认证,执行视图类的方法,处理了全局异常 -入口:APIView的dispatch -APIView的dispatch的496行上下:self.initial(request, *args, **kwargs) -APIView的initial -413行上下:有三句话,分别是:认证,权限,频率 self.perform_authentication(request) self.check_permissions(request) self.check_throttles(request) -读认证类的源码---》APIView的perform_authentication(request),315行上下 def perform_authentication(self, request): request.user # 新的request -request是新的request---》Request类中找user属性(方法),是个方法包装成了数据属性 -来到Request类中找:220行 def user(self): if not hasattr(self, '_user'): # Request类的对象中反射_user with wrap_attributeerrors(): self._authenticate() # 第一次会走这个代码 return self._user -Request的self._authenticate()---》373行 def _authenticate(self): for authenticator in self.authenticators: # 配置在视图类中所有的认证类的对象 try: #(user_token.user, token) user_auth_tuple = authenticator.authenticate(self) # 调用认证类对象的authenticate except exceptions.APIException: self._not_authenticated() raise if user_auth_tuple is not None: self._authenticator = authenticator # 忽略 self.user, self.auth = user_auth_tuple # 解压赋值 return # 认证类可以配置多个,但是如果有一个返回了两个值,后续的就不执行了 self._not_authenticated() # 总结:认证类,要重写authenticate方法,认证通过返回两个值或None,认证不通过抛AuthenticationFailed(继承了APIException)异常
-先读最简单的权限执行流程---》APIView的check_permissions(request),325行上下 def check_permissions(self, request): for permission in self.get_permissions(): # permission是咱们配置在视图类中权限类的对象,对象调用它的绑定方法has_permission # 对象调用自己的绑定方法会把自己传入(权限类的对象,request,视图类的对象) if not permission.has_permission(request, self): self.permission_denied( request, message=getattr(permission, 'message', None), code=getattr(permission, 'code', None) ) -APIVIew的self.get_permissions(),273行上下 return [permission() for permission in self.permission_classes] -self.permission_classes 就是咱们在视图类中配的权限类的列表 -所以这个get_permissions返回的是 咱们在视图类中配的权限类的对象列表[UserTypePermession(),] # 总结:权限类源码 -为什么要写一个类,重写has_permission方法,有三个参数,为什么一定要return True或False,messgage可以做什么用
5.鸭子类型
# 走路像鸭子,说话像鸭子,它就是鸭子 # 指的是面向对中,子类不需要显示的继承某个类,只要有某个的方法和属性,那我就属于这个类 # 假设有个鸭子类Duck类,有两个方法,run,speak方法 # 假设又有一个普通鸭子类,PDuck,如果它也是鸭子,它需要继承Duck类,只要继承了鸭子类,什么都不需要写,普通鸭子类的对象就是鸭子这种类型;如果不继承,普通鸭子类的对象就不是鸭子这种类型 #假设又有一个唐老鸭子类,TDuck,如果它也是鸭子,它需要继承Duck类,只要继承了鸭子类,什么都不需要写,唐老鸭子类的对象就是鸭子这种类型;如果不继承,唐老鸭子类的对象就不是鸭子这种类型 # python不推崇这个,它推崇鸭子类型,指的是 不需要显示的继承某个类,只要我的类中有run和speak方法,我就是鸭子这个类 # 有小问题:如果使用python鸭子类型的写法,如果方法写错了,它就不是这个类型了,会有问题 # python为了解决这个问题: -方式一:abc模块,装饰后,必须重写方法,不重写就报错 -方式二:drf源码中使用的:父类中写这个方法,但没有具体实现,直接抛异常
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现