Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask-SQLAlchemy: How to conditionally insert or update a row

My application uses a combination of Flask, Flask-SQLAlchemy, Flask-WTF and Jinja2.

In its current incarnation, I have a settings table. The table will only have one record with one field. Initially the table contains zero records.

What I want to achieve is:

  • Given that no entries exist in db, then show empty form ready for user input
  • Given that an entry exist, show the entry, and
  • if the user changes the value, then update the rec in db.

Here is my code:

models.py

class Provider(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    rssfeed = db.Column(db.String(120), unique = True)

    def __init__(self, rssfeed):
        self.rssfeed = rssfeed

    def __repr__(self):
        return '<NZBMatrix feed url %r>' % self.rssfeed

forms.py

class SettingsForm(Form):
    rssfeed = TextField('rssfed', validators= [Required()])

views.py

    @app.route('/settings', methods=["GET","POST"])
    def settings():
    """ show settings """
        provider = Provider.query.get(1)
        form = SettingsForm(obj=provider)
        print provider

        if request.method == "POST" and form.validate():
            if Provider.query.get(1) is None:
                provider = Provider(rssfeed=form.rssfeed.data)
                form.populate_obj(provider)
                db.session.add(provider)
                db.session.commit()
                flash("Settings added")

        return render_template("settings.html", form=form)

As it stands this code creates a record if it doesn't exists but the rssfeed column is empty.

How can I change this code so that it will INSERT if the record doesn't exist and UPDATE if it does?

like image 298
happygoat Avatar asked Jul 02 '12 11:07

happygoat


People also ask

How do you update existing table rows in SQLAlchemy in Python?

Update table elements in SQLAlchemy. Get the books to table from the Metadata object initialized while connecting to the database. Pass the update query to the execute() function and get all the results using fetchall() function. Use a for loop to iterate through the results.

How do I update my Flask?

First do conda create -n newname , then conda activate newname . Then you can do conda install -c conda-forge numpy pandas sklearn flask==2.0. 0 , you can also do pip install numpy pandas sklearn flask==2.0.

What is lazy in Flask-SQLAlchemy?

Lazy loading refers to objects are returned from a query without the related objects loaded at first. When the given collection or reference is first accessed on a particular object, an additional SELECT statement is emitted such that the requested collection is loaded.


2 Answers

Once your form is validated etc,

To add a new record:

new_provider = Provider(form.rssfeed.data)
db.session.add(new_provider)
db.session.commit()

To update an existing record:

existing_provider = Provider.query.get(1) # or whatever
# update the rssfeed column
existing_provider.rssfeed = form.rssfeed.data
db.session.commit()

The trick in updating is that you just have to change the particular field and do a commit. rest is taken care by the db session. I think you are using the merge function which is now deprecated in SQLAlchemy.

like image 90
codegeek Avatar answered Sep 21 '22 13:09

codegeek


I have managed to solve the problem doing these changes to the view.py file:

@app.route('/settings', methods=["GET","POST"])
def settings():
    """ show settings """
    provider = Provider.query.get(1)
    form = SettingsForm(request.form,obj=provider)

    if request.method == "POST" and form.validate():
        if provider:
            provider.rssfeed = form.rssfeed.data
            db.session.merge(provider)
            db.session.commit()
            flash("Settings changed")
            return redirect(url_for("index"))
        else:
            provider = Provider(form.rssfeed.data)
            db.session.add(provider)
            db.session.commit()
            flash("Settings added")
            return redirect(url_for("index"))
    return render_template("settings.html", form=form)
like image 41
happygoat Avatar answered Sep 23 '22 13:09

happygoat