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!
- 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.
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.
- FieldList and FormField are used to nest one Form inside another
phones
is a relation in theUser Model
creating a link toPhone entries
.PhoneForm
deals with the Phone fields onlyCombinedForm
includes theUser
andPhone
fields- The
CombinedForm
is populated through theUser
model and relatedphones
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.
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.
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)
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.
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.
Half working example Fixing populate_obj Error display in View FormField Documenation