Search code examples
flaskflask-sqlalchemykeyword-argument

updating table attributes using kwargs Flask-SQLAlchemy


I am using Flask-SQLAlchemy. I have a table with several attributes. I have a dictionary where key='attribute-name' and value=the_new_value.

I want to update an existing row/entry using the dictionary. Is there a way to update an entry using **kwargs rather than updating them one-at-a-time manually?

I found two references to a set_attribute method in SQLAlchemy: here and here, however both address more specific problems than the one I am asking.

I have tried set_attribute and it doesn't work for me. I don't get any error messages, but the database attributes do not change. I am wondering:

1) what is proper way to access/import set_attribute in Flask-SQLAlchemy?

2) can keys be stored as strings for **kwargs in set_attribute?

3) if neither 1) or 2) is my problem, what is?

As for code, this is kind of what it looks like, first the model:

class Files(UserMixin, db.Model):
    id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
    filename_main = db.Column(db.String(264))
    filename_side1 = db.Column(db.String(264))
    filename_side2 = db.Column(db.String(264))

    def update(self, **kwargs):
       for key, value in kwargs.items():
               set_attribute(self, key, value)

And in the view, I'd like to do something like this:

files = Files.query.filter_by(id=id).first()
filenames = {'filename_main': 'main.ext', 
             'filename_side1': 'side1.ext', 
             'filename_side2': 'side2.ext'}
files.update(**filenames)

Solution

  • I would implement update method this way:

    @staticmethod  
    def update(new_data, id):
                # note that this method is static and
                # you have to pass id of the object you want to update
        keys = new_data.keys() # new_data in your case is filenames
        files = Files.query.filter_by(id=id).first() # files is the record 
                                                     # you want to update
        for key in keys:
            exec("files.{0} = new_data['{0}']".format(key))
        db.session.commit()
    

    this solves your problem .