27

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.

3 Answers 3

30

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().

Sign up to request clarification or add additional context in comments.

7 Comments

I am still a bit confused. Once I am sending my user object in the form i need to edit the template also i think, otherwise how will the it associate the correct correct feild with models ? As data members in my user model and form class are having different names.
Why are they different? Also, can you show us the model?
Based on your EditProfile form above and your code on GitHub, the fields have the same names in your user model and form.
@dim what if I don't need to populate all the data from the form, populate_obj will try to mass assign all form fields but I only want to mass assge some of the form
|
16

The easiest way I've found of doing this is to fill the form fields on a get request.

@decorator_authorized_user  # This decorator should make sure the user is authorized, like @login_required from flask-login
def editprofile(nickname = None):
    # Prepare the form and user
    form = EditProfile()
    form_action = url_for('profile.editprofile')
    my_user = Users.get(...)  # get your user object or whatever you need
    if request.method == 'GET':
        form.username.data = my_user.username
        form.email.data = my_user.email
        # and on
    if form.validate_on_submit():
        # This section needs to be reworked.
        # You'll want to take the user object and set the appropriate attributes
        # to the appropriate values from the form.
        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")

This sets up the function to return a prefilled form on a get request. You'll have to rework the section under form.validate_on_submit. Dirn's answer suggests a few of the right things to do.

Comments

13

To populate the form with your SQLAlchemy object use:

form = EditProfile(obj=<SQLAlchemy_object>)

If your form fields don't match the database columns in your model for whatever reason (they should), the form class takes kwargs:

**kwargs – If neither formdata or obj contains a value for a field, the form will assign the value of a matching keyword argument to the field, if provided.

I found that one use case for this is if you have a form that contains fields that reference more than one model (e.g. through a relationship); passing the one obj isn't enough.

So let's take your example and say that in your database model (for user) you use site instead of website (the form field name). You'd do this to populate your form from the SQLAlchemy object:

form = EditProfile(obj=user, website=user.site)

Then in the POST you'd have to do this to populate your SQLAchemy object from your form:

form.populate_obj(user)
user.site = form.website.data
db.session.commit()

2 Comments

how can i repopulate MultiSelectField ? i don't mean to use obj, i want to use the field name but it doesn't work for me
I don't know why this example was so hard to find now in 2020 :^( Here is a page at PalletsProject about Select, Insert, Delete. Almost all the CRUD, but what about Update--SQLA obj into a WTForms object? %^\

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.