Reputation: 59
I want to automatically hash passwords before storing them.
from sqlalchemy.ext.hybrid import hybrid_property
from blog import db, bcrypt
...
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), nullable=False)
email = db.Column(db.String(64), nullable=False)
_password_hash = db.Column(db.String(128))
@hybrid_property
def password(self):
return self._password_hash
@password.setter
def _set_password(self, plain):
self._password_hash = bcrypt.generate_password_hash(plain)
Manually setting the _password_hash
property works fine:
>>> new = User(name='johndoe', email='[email protected]', _password_hash='strongpassword')
>>> new.password
'strongpassword'
But when I try to use the password
property I get this error:
>>> new.password = 'strongpassword'
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/toki/.local/lib/python3.8/site-packages/sqlalchemy/ext/hybrid.py", line 899, in __set__
raise AttributeError("can't set attribute")
AttributeError: can't set attribute
Another example:
>>> new = User(name='johndoe', email='[email protected]', password='strongpassword')
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "<string>", line 4, in __init__
File "/home/toki/.local/lib/python3.8/site-packages/sqlalchemy/orm/state.py", line 441, in _initialize_instance
manager.dispatch.init_failure(self, args, kwargs)
File "/home/toki/.local/lib/python3.8/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
compat.reraise(exc_type, exc_value, exc_tb)
File "/home/toki/.local/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 153, in reraise
raise value
File "/home/toki/.local/lib/python3.8/site-packages/sqlalchemy/orm/state.py", line 438, in _initialize_instance
return manager.original_init(*mixed[1:], **kwargs)
File "/home/toki/.local/lib/python3.8/site-packages/sqlalchemy/ext/declarative/base.py", line 842, in _declarative_constructor
setattr(self, k, kwargs[k])
File "/home/toki/.local/lib/python3.8/site-packages/sqlalchemy/ext/hybrid.py", line 899, in __set__
raise AttributeError("can't set attribute")
AttributeError: can't set attribute
How do I fix it? Why it doesn't work?
Upvotes: 1
Views: 687
Reputation: 1053
Not really used to SQLAlchemy and had no idea about hybrid properties, but by judging on how it is structured, I think the setter method should have the same property name like as the hybrid one.
Something like:
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), nullable=False)
email = db.Column(db.String(64), nullable=False)
_password_hash = db.Column(db.String(128))
@hybrid_property
def password(self):
return self._password_hash
@password.setter
def password(self, plain):
self._password_hash = bcrypt.generate_password_hash(plain)
Again, my knowledge is limited on SQLAlchemy (using psycopg2 for my projects at the moment).
Upvotes: 4