bear
bear

Reputation: 663

Sqalchemy postgres: AttributeError: can't set attribute

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

Answers (2)

mirth23
mirth23

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

Metalstorm
Metalstorm

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

Related Questions