Pre-Populate a WTforms in flask, with data from a SQLAlchemy object

Hammad Haleem picture Hammad Haleem · May 17, 2014 · Viewed 29.8k times · Source

I am fairly new to flask framework and was creating an edit profile page for a webportal. I am stuck at a point and am unable to autofill a form.

Here is my form class :

class EditProfile(Form):

    username = TextField('Username', [Required()])
    email = TextField('Email', [Required()])
    about = TextAreaField('About', [Required()])
    website = TextField('Website', [Required()])

This is my function that evaluates the form.

def editprofile(nickname = None):
    if g.fas_user['username'] == nickname  or request.method == 'POST':
        form = EditProfile()
        form_action = url_for('profile.editprofile')
        if request.method == 'POST' and form.validate():
            if form.username.data == nickname : 
              query = EditProfile(form.username.data,
                                 form.email.data,
                                 form.about.data,
                                 form.website.data,
                                 )
              print query #debug
              db.session.add(query)
              db.session.commit()
              flash('User Updated')
              print "added"
            return(url_for('profile.editprofile'))
        return render_template('profile/add.html', form=form,
                               form_action=form_action, title="Update Profile")
    else:
        return "Unauthorised"

And my html template for form is form is :

{% extends "base.html" %}
    {% block title %}
        {{ title }}
    {% endblock %}
    {% block content %}
    {% from "_formhelpers.html" import render_field %}
    <div id="Edit Profile">
        <h2>{{  title  }}</h2>
        <form method="post" action="{{ form_action }}">
            <fieldset>
                <legend></legend>
                {{ render_field(form.username) }}
                {{ render_field(form.email)}}
                {{ render_field(form.about )}}
                {{ render_field(form.website) }}
            </fieldset>
        <input type="submit" class="button" value="Save"/>
    </form>
    </div>
    {% endblock %}


I have an object, of user class. And from that object I want to prefill this form.How can I prepopulate the values in the form. I am trying to implement the edit profile functionality here.

Answer

dirn picture dirn · May 17, 2014

You need to pass your object to the form when you create it.

form = EditProfile(obj=user)  # or whatever your object is called

You're going to run into some trouble with

          query = EditProfile(form.username.data,
                             form.email.data,
                             form.about.data,
                             form.website.data,
                             )
          db.session.add(query)

It creates a new instance of your EditProfile form. You then try to add it to the session. The session wants models, not forms.

Instead, after validating the form, you can associate its values with the object.

form.populate_obj(user)  # or whatever your object is called

Because your object was already loaded, you won't need to add it to the session. You can remove db.session.add(query) and just call db.session.commit().