Amin Etesamian Amin Etesamian - 1 month ago 11
Python Question

Sqlalchemy: automatically calculate the value of a column upon another column changed

I want the value of a column (

is_dangerous_token
) to be calculated using a method.
Here is what I have gone so far.

class PassRecovery(DeclarativeBase):
__tablename__ = 'pass_recoveries'

id = Column(Integer, primary_key=True)
account_email_address = Column(Unicode(255), ForeignKey('accounts.email_address'), index=True)
account = relationship('Account', backref=backref('pass_recoveries', cascade='all, delete-orphan'))
_is_dangerous_token = Column('is_dangerous_token', Unicode(255))

def _set_is_dangerous_token(self, account_email_address):
secret_key = config.get('is_dangerous_key')
signer = TimestampSigner(secret_key)
self._is_dangerous_token = signer.sign(account_email_address)

def _get_is_dangerous_token(self):
return self._is_dangerous_token

is_dangerous_token = synonym(
'_is_dangerous_token',
descriptor=property(_get_is_dangerous_token, _set_is_dangerous_token)
)


But the problem is that when I create a row by passing in the email_address, the
is_dangerous_token
is not generated using the code I wrote. The created row only has the
id
and the relation to the
account
and
is_dangerous_token
has no value in the database.
thanks for any help

Answer

You have to use synonym on the account_email_address column, because you need it's value to generate the token:

class PassRecovery(DeclarativeBase):
    __tablename__ = 'pass_recoveries'

    id = Column(Integer, primary_key=True)
    _account_email_address = Column(Unicode(255), ForeignKey('accounts.email_address'), index=True)
    account = relationship('Account', backref=backref('pass_recoveries', cascade='all, delete-orphan'))
    is_dangerous_token = Column('is_dangerous_token', Unicode(255))

    def _set_account_email_address(self, account_email_address):
        self._account_email_address = account_email_address

        if self.is_dangerous_token is None:
            secret_key = config.get('is_dangerous_key')
            signer = TimestampSigner(secret_key)
            self.is_dangerous_token = signer.sign(self._account_email_address)


    def _get_account_email_address(self):
        return self.account_email_address

    account_email_address = synonym(
        '_account_email_address',
        descriptor=property(_get_account_email_address, _set_account_email_address)
    )
Comments