Django自定义密码验证器如何获取请求变量读取数据库配置?
Django自定义密码验证器获取客户端ID的替代方案
方法1:实例化验证器时传入客户端ID
在处理密码修改、用户创建的视图或表单中,直接从request提取客户端ID,初始化验证器时传入该ID,再用它查询数据库中的密码策略。
修改验证器类:
class MinimumLengthValidator: """验证密码是否符合最小长度要求。""" def __init__(self, client_id=None): self.client_id = client_id # 根据client_id读取数据库配置 if self.client_id: client_config = ClientConfig.objects.get(client_id=self.client_id) self.min_length = client_config.password_min_length else: self.min_length = 8 # 默认长度 def validate(self, password, user=None): if len(password) < self.min_length: raise ValidationError( f"密码长度至少为{self.min_length}位。", code='password_too_short', ) def get_help_text(self): return f"密码长度至少为{self.min_length}位。"
视图中调用示例:
def change_password(request): client_id = request.client.id # 假设request已绑定client对象 # 初始化验证器时传入client_id validators = [MinimumLengthValidator(client_id=client_id)] if request.method == 'POST': form = PasswordChangeForm(user=request.user, data=request.POST, validators=validators) # 后续表单校验、保存逻辑...
方法2:用线程局部存储传递客户端ID
通过Django中间件把客户端ID存入线程局部变量,验证器直接读取该变量获取配置。
先创建中间件:
# middleware.py import threading local_storage = threading.local() class ClientIDMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): # 从request提取client_id并存入线程存储 if hasattr(request, 'client'): local_storage.client_id = request.client.id else: local_storage.client_id = None response = self.get_response(request) # 请求结束后清理变量,避免内存泄漏 if hasattr(local_storage, 'client_id'): del local_storage.client_id return response
把中间件添加到settings.py的MIDDLEWARE列表:
MIDDLEWARE = [ # 其他中间件... 'your_app.middleware.ClientIDMiddleware', ]
修改验证器类:
from .middleware import local_storage class MinimumLengthValidator: """验证密码是否符合最小长度要求。""" def __init__(self): self.min_length = 8 # 默认值 # 从线程存储读取client_id并加载配置 client_id = getattr(local_storage, 'client_id', None) if client_id: try: client_config = ClientConfig.objects.get(client_id=client_id) self.min_length = client_config.password_min_length except ClientConfig.DoesNotExist: pass # 配置不存在则用默认值 def validate(self, password, user=None): if len(password) < self.min_length: raise ValidationError( f"密码长度至少为{self.min_length}位。", code='password_too_short', ) def get_help_text(self): return f"密码长度至少为{self.min_length}位。"
方法3:从用户实例关联的客户端获取ID
如果你的User模型和客户端模型存在外键关联(比如User有client字段),可以在验证器的validate方法中通过user参数提取客户端ID:
class MinimumLengthValidator: """验证密码是否符合最小长度要求。""" def __init__(self): self.min_length = 8 # 默认值 def validate(self, password, user=None): if user and hasattr(user, 'client'): try: client_config = ClientConfig.objects.get(client_id=user.client.id) self.min_length = client_config.password_min_length except ClientConfig.DoesNotExist: pass if len(password) < self.min_length: raise ValidationError( f"密码长度至少为{self.min_length}位。", code='password_too_short', ) def get_help_text(self): return f"密码长度至少为{self.min_length}位。"
注意:这种方法依赖validate方法传入user参数,Django内置的密码修改表单会自动传递该参数,但自定义场景需要确保user被正确传入。
内容的提问来源于stack exchange,提问作者Toby Smith
相关产品推荐
相关产品推荐

