You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 01:53:21