4

I have a class shown below:

class Account(db.Model, flask_login.UserMixin):
    __tablename__ = 'account'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(75))
    username = db.Column(db.String(50))
    password = db.Column(db.String(250))
    admin = db.Column(db.Boolean)

    def __init__(self, email='', username='', password='', admin=None):
        self.email = email
        self.username = username
        self.password = password
        self.admin = admin

    def __repr__(self):
        return '<Account %r>' % self.username

When I create an account through a form, the admin attribute will be None. However when I access the database and try to manually set it to True, the attribute will update but when I access the database again, the attribute is None It's super annoying.

Here is what I execute on the console:

account = Account.query.get(1)
account.admin = True
db.session.commit()
db.admin ----> True

exit()

#restart again
account = Account.query.get(1)
account.admin ----> None

What am I doing wrong?

Dan Rubio
  • 4,709
  • 10
  • 49
  • 106
  • `get` doesn't necessary re-fetch the record. Are you sure you have a clean session when `account.admin` is `None`? – univerio Jun 10 '16 at 02:03
  • Pretty sure this was yet another case of having more than one instance of `db`, and so the session used by `Account.query` is not the same as `db.session`. – Ilja Everilä Nov 27 '18 at 05:08

2 Answers2

6

Just do this:

account = Account.query.get(1)
account.admin = True
db.session.merge(account)
db.session.commit()

The changes are going to be detected and sent to the database.

The instance you have and the object in the session not necessarily are the same - despite they represent the same thing - they aren't the same object. In Flask-SqlAlchemy there is a config SQLALCHEMY_TRACK_MODIFICATIONS that makes sqlalchemy work as you want. But it's very expensive, since the orm will have to monitor changes made on all of your instances.

Hope this helps!

Jayme Tosi Neto
  • 1,189
  • 2
  • 19
  • 41
  • unfortunately this doesn't work for me, i've been searching the whole day without any luck ! please, any help will be appreciated. – BHA Bilel May 21 '20 at 03:33
  • 1
    @danibilel it depends a lot on how you setup your project. You could try using db.session.refresh(account) to get the latest data of your instance from the db. But I can't say for sure it's going to work. I think it's the case of opening a question for that ;) – Jayme Tosi Neto May 21 '20 at 21:28
  • Hello, thanks for your suggestion, i wish i could ask a question but i can't because of the website policy, this question is much similar to mine. While i can normally manipulate data in the database, i can't update the current_user, so it's rather a flask_login problem than a database problem, thanks for your help ! – BHA Bilel May 22 '20 at 00:15
-3

The change to the object is not added to the session. So correct way would be

account = Account.query.get(1)
account.admin = True
db.session.add(account)
db.session.commit()
  • 2
    Why would you add account to the session? It already exists in the database, otherwise Account.query.get(1) would be none. – Amin Alaee Jun 10 '16 at 08:04
  • `db.session` is not only used to create new database record i.e. __insert queries__. The updates to the database are also managed through it. So above __update query__ must be added to it. – Digvijay Chougale Jun 10 '16 at 08:42
  • I know what db.session does. The problem is with your db.session.add(account) which adds the Account instance to the session and finally when calling commit(), it will be added to the database. See this http://stackoverflow.com/questions/6699360/flask-sqlalchemy-update-a-rows-information – Amin Alaee Jun 10 '16 at 08:50