Flask-SQLalchemy update a row's information

前端 未结 5 2030
南方客
南方客 2020-12-02 03:59

How can I update a row\'s information?

For example I\'d like to alter the name column of the row that has the id 5.

相关标签:
5条回答
  • 2020-12-02 04:43

    This does not work if you modify a pickled attribute of the model. Pickled attributes should be replaced in order to trigger updates:

    from flask import Flask
    from flask.ext.sqlalchemy import SQLAlchemy
    from pprint import pprint
    
    app = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqllite:////tmp/users.db'
    db = SQLAlchemy(app)
    
    
    class User(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(80), unique=True)
        data = db.Column(db.PickleType())
    
        def __init__(self, name, data):
            self.name = name
            self.data = data
    
        def __repr__(self):
            return '<User %r>' % self.username
    
    db.create_all()
    
    # Create a user.
    bob = User('Bob', {})
    db.session.add(bob)
    db.session.commit()
    
    # Retrieve the row by its name.
    bob = User.query.filter_by(name='Bob').first()
    pprint(bob.data)  # {}
    
    # Modifying data is ignored.
    bob.data['foo'] = 123
    db.session.commit()
    bob = User.query.filter_by(name='Bob').first()
    pprint(bob.data)  # {}
    
    # Replacing data is respected.
    bob.data = {'bar': 321}
    db.session.commit()
    bob = User.query.filter_by(name='Bob').first()
    pprint(bob.data)  # {'bar': 321}
    
    # Modifying data is ignored.
    bob.data['moo'] = 789
    db.session.commit()
    bob = User.query.filter_by(name='Bob').first()
    pprint(bob.data)  # {'bar': 321}
    
    0 讨论(0)
  • 2020-12-02 04:48

    There is a method update on BaseQuery object in SQLAlchemy, which is returned by filter_by.

    admin = User.query.filter_by(username='admin').update(dict(email='my_new_email@example.com')))
    db.session.commit()
    

    The advantage of using update over changing the entity comes when there are many objects to be updated.

    If you want to give add_user permission to all the admins,

    rows_changed = User.query.filter_by(role='admin').update(dict(permission='add_user'))
    db.session.commit()
    

    Notice that filter_by takes keyword arguments (use only one =) as opposed to filter which takes an expression.

    0 讨论(0)
  • 2020-12-02 04:49

    In RestApi, We can update the record dynamically by passing the json data into update query:

    class UpdateUserDetails(Resource):
    @auth_token_required
    def post(self):
        json_data = request.get_json()
        user_id = current_user.id
        try:
            userdata = User.query.filter(User.id==user_id).update(dict(json_data))
            db.session.commit()
            msg={"msg":"User details updated successfully"}
            code=200
        except Exception as e:
            print(e)
            msg = {"msg": "Failed to update the userdetails! please contact your administartor."}
            code=500
        return msg
    
    0 讨论(0)
  • 2020-12-02 04:53

    Retrieve an object using the tutorial shown in the Flask-SQLAlchemy documentation. Once you have the entity that you want to change, change the entity itself. Then, db.session.commit().

    For example:

    admin = User.query.filter_by(username='admin').first()
    admin.email = 'my_new_email@example.com'
    db.session.commit()
    
    user = User.query.get(5)
    user.name = 'New Name'
    db.session.commit()
    

    Flask-SQLAlchemy is based on SQLAlchemy, so be sure to check out the SQLAlchemy Docs as well.

    0 讨论(0)
  • 2020-12-02 05:00

    Just assigning the value and committing them will work for all the data types but JSON and Pickled attributes. Since pickled type is explained above I'll note down a slightly different but easy way to update JSONs.

    class User(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(80), unique=True)
        data = db.Column(db.JSON)
    
    def __init__(self, name, data):
        self.name = name
        self.data = data
    

    Let's say the model is like above.

    user = User("Jon Dove", {"country":"Sri Lanka"})
    db.session.add(user)
    db.session.flush()
    db.session.commit()
    

    This will add the user into the MySQL database with data {"country":"Sri Lanka"}

    Modifying data will be ignored. My code that didn't work is as follows.

    user = User.query().filter(User.name=='Jon Dove')
    data = user.data
    data["province"] = "south"
    user.data = data
    db.session.merge(user)
    db.session.flush()
    db.session.commit()
    

    Instead of going through the painful work of copying the JSON to a new dict (not assigning it to a new variable as above), which should have worked I found a simple way to do that. There is a way to flag the system that JSONs have changed.

    Following is the working code.

    from sqlalchemy.orm.attributes import flag_modified
    user = User.query().filter(User.name=='Jon Dove')
    data = user.data
    data["province"] = "south"
    user.data = data
    flag_modified(user, "data")
    db.session.merge(user)
    db.session.flush()
    db.session.commit()
    

    This worked like a charm. There is another method proposed along with this method here Hope I've helped some one.

    0 讨论(0)
提交回复
热议问题