微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何以经典方式映射 SqlAlchemy 中的 getter 属性?

如何解决如何以经典方式映射 SqlAlchemy 中的 getter 属性?

我有以下课程:

class Password:

    def __init__(self,encryptor: AbstractEncryptor,value: str = None):
        self._encryptor = encryptor
        self._value = value

    def __repr__(self):
        return '<Password object {}>'.format(self._value)

    def __eq__(self,value: str) -> bool:
        return self._encryptor.verify(value,self._value)

    @property
    def value(self) -> str:
        return self._value

    @classmethod
    def validate_strength(cls,value: str) -> (bool,dict):
        """
        Verify the strength of 'password',it returns a dict with
        bool values for each validation.

        A password is considered strong if:
            8 characters length or more
            1 digit or more
            1 symbol or more
            1 uppercase letter or more
            1 lowercase letter or more
        """

        if value is None:
            return False,{}

        length = cls._is_longer_than_7(value)
        digit = cls._has_digit(value)

        is_valid = all([length,digit])
        error_dict = {
            'length': length,'digit': digit
        }

        return is_valid,error_dict

    @classmethod
    def _is_longer_than_7(cls,value):
        return not len(value) < 8

    @classmethod
    def _has_digit(cls,value):
        return bool(re.search(r"\d",value))

    @value.setter
    def value(self,value: str):
        valid_password,_ = self.validate_strength(value)
        if not valid_password:
            raise exceptions.PasswordStrengthError(
                'A strong password should contain at least 8 characters,'
                '1 digit,1 symbol,1 uppercase letter,and 1 lowercase '
                'letter'
            )
        self._value = self._encryptor.encrypt(value)

class Credential:

    def __init__(
            self,username: str,password: str = None,encryptor: AbstractEncryptor = Encryptor,active: bool = True
    ):
        self.username = username
        self._password = Password(encryptor,password)
        self._active = active

    @property
    def password(self):
        return self._password.value

    @password.setter
    def password(self,value: str):
        self._password.value = value

    def __eq__(self,other: Credential) -> bool:
        return (self.username == other.username and
                self._password.value == other.password)

    def verify_password(self,value: str) -> bool:
        return self._password == value

    def deactivate(self):
        self.active = False

我正在尝试使用 sqlAlchemy 中的经典映射来映射 Credential

credentials = Table('credentials',Metadata,Column('id',Integer,primary_key=True,autoincrement=True),Column('username',String,index=True,unique=True,nullable=False),Column('password',Column('active',Boolean)
                    )

mapper(credential.Credential,credentials,properties={
    'password': synonym('_password',map_column=True,descriptor=credential.Credential.password)
})

但问题是我无法让 sqlAlchemy 看到我在 getter 中定义的密码的实际字符串值。然后,当我尝试运行它时,它会引发 InterfaceError,因为它尝试保存 Password 对象而不是字符串。我需要让它保存 Password 的计算值。

PS:我知道可以使用 hybrid_property 来实现,但它似乎只在声明性映射中可用。有没有办法在经典映射中做到这一点?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。