Reputation: 663
When initializing my postgres database with sqalchemy, I am getting an AttributeError: can't set attribute error:
Traceback (most recent call last):
File "manage.py", line 567, in <module>
manager.run()
File "/usr/local/lib/python3.6/site-packages/flask_script/__init__.py", line 417, in run
result = self.handle(argv[0], argv[1:])
File "/usr/local/lib/python3.6/site-packages/flask_script/__init__.py", line 386, in handle
res = handle(*args, **config)
File "/usr/local/lib/python3.6/site-packages/flask_script/commands.py", line 216, in __call__
return self.run(*args, **kwargs)
File "manage.py", line 26, in initdb
password="passwo",
File "<string>", line 4, in __init__
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/state.py", line 417, in _initialize_instance
manager.dispatch.init_failure(self, args, kwargs)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/util/langhelpers.py", line 66, in __exit__
compat.reraise(exc_type, exc_value, exc_tb)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 187, in reraise
raise value
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/state.py", line 414, in _initialize_instance
return manager.original_init(*mixed[1:], **kwargs)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/ext/declarative/base.py", line 700, in _declarative_constructor
setattr(self, k, kwargs[k])
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/ext/hybrid.py", line 873, in __set__
raise AttributeError("can't set attribute") AttributeError: can't set attribute
The table is defined like this:
class User(db.Model, UserMixin):
"""
A user who has an account on the website.
"""
__tablename__ = 'user'
id = db.Column(db.Integer,
primary_key=True,
nullable=False,
unique=True,
autoincrement=True)
first_name = db.Column(db.String)
last_name = db.Column(db.String)
phone = db.Column(db.String)
email = db.Column(db.String, unique=True)
photo = db.Column(db.String, default="No Picture")
_password = db.Column(db.Binary(60))
and initialized like this:
def initdb():
''' Create the SQL database. '''
db.create_all()
print(colored('The SQL database has been created', 'green'))
user2 = models.User(
first_name="Jane",
last_name="Doe",
phone="123",
email="[email protected]",
password="passwo",
)
db.session.add(user2)
How can I initialize the database correctly?
UPDATE 1: I downgraded my SQLAlchemy from 1.2.5 to 1.1.15 (following the suggestion in https://github.com/puckel/docker-airflow/issues/160 and the error disappears. Is there a way to circumvent the error in 1.2.5?
Upvotes: 3
Views: 3366
Reputation: 387
The probable issue is that you are using a hybrid property for password and a custom setter, which is common in Flask examples and looks something like:
Class User(db.Model)
...
@hybrid_property
def password(self):
return self._password
@password.setter
def _set_password(self, plaintext):
self._password = bcrypt.generate_password_hash(plaintext).decode('utf-8')
For consistency with Python properties, SQLAlchemy decided to disallow the use of functions called something other than the name of the hybrid proprerty that they affect. So the above now needs to be:
@hybrid_property
def password(self):
return self._password
@password.setter
def password(self, plaintext):
self._password = bcrypt.generate_password_hash(plaintext).decode('utf-8')
See https://docs.sqlalchemy.org/en/latest/orm/extensions/hybrid.html for more details.
Upvotes: 4
Reputation: 3232
In your class you have:
_password = db.Column(db.Binary(60))
In you object initalize you have:
password="passwo"
They should match
Upvotes: 1