Dynamic Flask Form

Having struggled to find a workind example of a WTForm in Flask with a dynamic form, I created this one. It is cobbled together from a few Stackoverflow and Google Group discussions.

I'm a total noob so if you have suggestions I'd be glad to include them!

What does it do?

  • Render a form with two models
  • Save and load the related models

This means you can have a form with dynamically created fields which are saved and loaded properly.

Usage

You can use requirements.txt to install the packages, preferably in a virtualenv. Then you can simply run multimodel.py. The default port is set to 5002.

Basic Concepts

  • FieldList and FormField are used to nest one Form inside another
  • phones is a relation in the User Model creating a link to Phone entries.
  • PhoneForm deals with the Phone fields only
  • CombinedForm includes the User and Phone fields
  • The CombinedForm is populated through the User model and related phones

Pain Points

User Model

I had named the phones relation phone for a while which broke the populate_obj function. The naming must match for the mechanism to work. Duh.

PhoneForm

This is the form that is nested in the 'main' Form. It is not directly exposed or rendered. A common problem here is the CSRF token being missing from this form. Options to solve this problem are explained here. I chose to subclass wtforms Form which does not require the token.

CombinedForm

phones = FieldList(FormField(PhoneForm, default=lambda: Phone()))

That is the line of code where it all broke down for me. Once there is a working example it's hopefully not so mysterious. Setting the default to lambda: Phone() was difficult for me to get to (see Fixing populate_obj)

Index

I just load the one user from the db, no messing around. Playing with a dropdown for different users just distracts from the main point here.

I'm not sure if aassing a new Phone instance where the User has no phones is the best possible solution but it meant I could keep using the JavaScript Code as it was.

Javascript

I simply fixed example code that I found. There is probably a neater way of copying the fields that I haven't found. I would gladly take suggestions in this case as well as the rest of the code.

Resources

Half working example Fixing populate_obj Error display in View FormField Documenation