0

I am writing a small app that consists of forms and sub forms leveraging flask_wtf. I wish to prepopulate the forms with known values (from json) before the user starts editing. Despite a lot of hunting, most documentation or examples/ questions don’t include sub forms, or refer to dynamically updating sub forms after the user submits.

This code below demonstrates what I have tried so far. It seems to work with the exception of populate_obj. I can prepopulate the main form by passing “obj=my_data()”, but have not discovered how to structure the obj to populate sub forms. I can also update via setting .data, but I have not seen this approach using (form.subform.form.name.data = “x”)to update sub forms anywhere else , so I strongly suspect its incorrect.

Appreciate any help/ insights.

app.py

from flask import Flask, render_template
from flask_wtf import FlaskForm
from wtforms import StringField, FormField
from wtforms.validators import InputRequired, Length

app = Flask(__name__)
app.config["SECRET_KEY"] = "Mysecret!"


class sub_form(FlaskForm):
    favorite_food = StringField(
        "Favorite Food",
        validators=[
            InputRequired("A entry is required!"),
            Length(min=4, max=20, message="Entry must be between 4 and 20 characters"),
        ],
        default="Pineapple",
    )


class main_form(FlaskForm):
    user_name = StringField(
        "Your name",
        validators=[
            InputRequired("Field is required!"),
            Length(min=4, max=20, message="Name must be between 4 and 20 characters"),
        ],
    )
    first_subform = FormField(sub_form)


class name:
    user_name = "Bert"


class fruit:
    favorite_food = "bananas"


@app.route("/", methods=["GET", "POST"])
def index():

    # Create the main form, populate name with "Bert"
    form = main_form(obj=name())

    # Update the main form user_name with "Ernie"
    form.user_name.data = "Ernie"

    # Update the sub form favorite food with "oranges".I suspect this is not optimal. 
    form.first_subform.form.favorite_food.data = "oranges"

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


if __name__ == "__main__":
    app.run(debug=True)

index_test.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
</head>

<body>
    <div>
        <form action="/" method="POST">
            {{ form.csrf_token }}

            {{form.user_name.label}}  {{form.user_name(size=20)}}
            <br>
            {{form.first_subform.favorite_food.label}}  {{form.first_subform.favorite_food(size=20)}}
            <br>
            <input type="submit" value="Submit">
        </form>
    </div>
</body>
</html>

1 Answers1

0

While wtforms can be nested - and nested form data can be accessed with a format such as form.Level1Form.form.Level2Form.name.data, the approach causes downstream challenges with modelling etc. I concluded that it is better to keep the forms independent, and render the forms using multiple view like this:

return render_template('index.html', register_form=register_form, login_form=login_form)

Referenced from the updated answer to this question.