元类如何访问子类定义的属性?基于DRF权限类封装的实现问题
解决方案
你可以通过给抽象基类加跳过校验标记的方式实现需求,只需要两步修改:
- 调整元类逻辑,新增抽象类跳过规则,同时修复原代码中类属性赋值不生效的问题(元类
__init__执行时类已创建完成,直接修改attrs不会更新类属性,需操作当前类对象self):
from rest_framework.permissions import BasePermission class ScopedPermissionMeta(type(BasePermission)): def __init__(self, name, bases, attrs): # 标记为__abstract__的类跳过required_scopes校验 if attrs.get('__abstract__', False): return try: required_scopes = attrs['required_scopes'] except KeyError: raise TypeError(f'{name} must include required_scopes attribute.') required_scopes_list = ' '.join(required_scopes) # 直接给类对象绑定属性 self.message = f'Resource requires scope={required_scopes_list}' def has_permission(self, request, _view): """Check required scopes against requested scopes.""" try: requested_scopes = request.auth.claims['scope'] except (AttributeError, KeyError): return False return all(scope in requested_scopes for scope in required_scopes) # 直接给类对象绑定方法 self.has_permission = has_permission
- 给中间基类添加
__abstract__标记,元类会自动跳过对它的校验:
class ScopedPermission(BasePermission, metaclass=ScopedPermissionMeta): __abstract__ = True
修改完成后业务子类的写法完全符合你的预期:
class ReadJwtPermission(ScopedPermission): required_scopes = ['read:jwt']
该方案支持多层继承扩展,如果后续需要新增中间通用基类,只需要给对应类加上__abstract__ = True即可跳过校验,不会影响业务层的使用。
内容的提问来源于stack exchange,提问作者Brady Dean
相关产品推荐
相关产品推荐

