Reputation: 63
I spent all yesterday on this issue. Saw Q Nested WTForms FieldList results in HTML in fields and some others.
I've got a MembersForm composed of a FieldList of a MemberForm FormField which, in turn, has an AddressForm FormField. Say:
class AddressForm(Form):
"""Form to collect addresses from GMaps API `address_components` field."""
formatted_address = StringField(
label="indirizzo visualizzato", validators=[DataRequired()]
)
administrative_area_level_1 = StringField(
label="regione", validators=[DataRequired()]
)
administrative_area_level_2 = StringField(
label="provincia", validators=[DataRequired()]
)
class MemberForm(Form):
"""Form for user data collection."""
name = StringField()
address = FormField(AddressForm)
class MembersForm(FlaskForm):
"""List of MemberForm."""
members = FieldList(FormField(MemberForm))
I need to populate MembersForm with some initial partial data, namely the nested AddressForm.
Then, in my Flask app route:
@app.route('/members')
def members():
form = MembersForm()
# If this is the first loading of the page, fill in some data from session:
if request.method == 'GET' and session.get('places', False):
for p in [ place for place in session['places'] if place.get('is_valid', False) ]:
address = p['address']
address.update({
'category': 'pod',
'formatted_address': p['title']
})
form.members.append_entry(MemberForm(data={
'place_id': p['id'],
'address': address
}))
form.validate()
return render_template(
'members.jinja', form=form)
This approach does not work because:
for
attributes are working...):<label for="members-1-address-street_number">numero civico</label>
<input id="address-street_number" name="address-street_number" type="text" value="52">
member.name.data
):{% for member in form.members %}
<!-- Some ugly workaround ↓ -->
<li id="{{ member.data.name.data }}">
<span>{{ member.data.address.formatted_address.data }}</span>
<!-- This works as expected ↓ -->
{{ member.category.label(class="form-label") }}
{{ member.category(class="form-select") }}
<span class="form-text">{{ member.category.description }}</span>
<!-- AddressForm part is pretty ugly and strange: without using data attribute
WTForms render the HTML inside the input value. -->
{% for field in [ "administrative_area_level_1", "administrative_area_level_2" ] %}
{{ member.address[field].label() }}
{{ member.address[field].data(title=member.address[field].description) }}
{% endfor %}
See cited SO question for this solution. But I cannot use their enumerate()
solution to make form works.
Previously I attempted to load data via werkzeug.datastructures.MultiDict
, but I do not understand how.
EDIT: I also unsuccesfully tried to first populate AddressForm, then feed MemberForm, then append it to MembersForm.
By the way, I was wondering if in those cases WTForms worth the work. Actually, if I could have form inputs with the same name
and browsers preserve order while POSTing it seems a bit overwhelming. What do you think?
Thanks in advance.
EDIT: I add some data to play with:
[
{
'address': {
'administrative_area_level_1': 'Veneto',
'administrative_area_level_2': 'Città Metropolitana di Venezia',
'administrative_area_level_3': 'Pianiga',
'locality': 'Pianiga',
'postal_code': '30030',
'prov': 'VE',
'route': 'Via G. Puccini',
'street_number': ''
},
'id': 'ChIJhX9gFYzPfkcR3kaULLuW6SQ',
'is_main': True,
'is_valid': True,
'location': {'lat': 45.4569727, 'lng': 11.995981599999999},
'title': 'Via G. Puccini, 30030 Pianiga VE'
}
]
Upvotes: 0
Views: 60
Reputation: 63
Sorry guys, my fault.
Thanks to this SO answer Filling WTForms FormField FieldList with data results in HTML in fields I found out that feeding initial data as a python object works:
address = p['address']
address.update({
'category': 'pod',
'formatted_address': p['title']
})
form.members.append_entry(data={
'place_id': p['id'],
'address': address
})
Or with a MultiDict
:
address = p['address']
address.update({
'category': 'pod',
'formatted_address': p['title']
})
form.members.append_entry(MultiDict({
'place_id': p['id'],
'address': address
}))
Upvotes: 0