Reputation: 1108
I have a weird problem with flask, flask-wtforms and flask-sqlalchemy.
I have the following form:
class CompEditForm(Form):
name = StringField('Company name', validators = [Required()])
desc = TextAreaField('Description')
address = StringField('Adress', validators = [Required()])
...
sectors = SelectMultipleField(u'Sectors', coerce=int)
submit = SubmitField(u'Save changes')
when I write a flask view for editing the company:
def edit_company(id):
comp = Company.query.get_or_404(id)
form = CompEditForm(request.form,comp)
the above code prepopulates the form with all the fields like name, description etc. Since a company can operate in different sectors, I modeled that with a many-to-many relationship. I try to populate the form's SelectMultipleFiled with the following:
form.sectors.choices = [(g.id, g.name_srb) for g in Sector.query.order_by('name')]
and so far so good, the form is populated with the sectors and it works nice. This is the same as the form for creating new companies. The problem arises when I wish to prepopulate the editing form with the existing sectors:
form.sectors.data = [c.id for c in comp.sectors.all()]
It populates the form with the right sectors, i.e. they are selected upon rendering, but when I submit the form, they just don't change and match the user's input. They remain the same:
if form.validate_on_submit():
print form.sectors.data # stays the same, not taking account of the user's new choice
Any idea? I tried with the default argument instead of data, but it does not prepopulate with any sectors.
Upvotes: 0
Views: 2887
Reputation: 1108
I have tried Sadeghi's solution, but, as I stated it simply did not populate the form with the initial data. At the end, I found the sqlalchemy extension for WTForms and I used the QuerySelectMultipleField:
sectors = QuerySelectMultipleField(query_factory=all_sectors, allow_blank=True)
instead of the simple MultipleSelectField. The all_sectors factory is the simple query defined with>
def all_sectors():
return Sector.query.all()
The submiutted form, however, returns a queryset object, not the usual Names/IDs combination, so in the code for updating the company data I can simply put:
for sec in comp.sectors:
comp.sectors.remove(sec)
if form.sectors.data:
for sek in form.sectors.data:
comp.sectors.append(sek)
I honestly do not know why Sadeghi's solution did not work for me, my solution is more complicated and uglier but it works. Thank you Sadeghi.
Upvotes: 0
Reputation: 5154
As far as I see with initializing data directly the internals of wtf Field looses track of correct object. But there is another way to initialize your field. Pass the desired data directly to the form upon initializing. Field
's process method will take care of initializing the rest:
form = CompEditForm(request.form, comp, sectors=[c.id for c in comp.sectors.all()])
Upvotes: 1