When you’re reading on this articles, maybe you’re like me struggling in how to pre-populate the values from saved data.
Models:
class Category(db.Model): __tablename__ = 'category' id = db.Column(db.Integer, primary_key=True) name_en = db.Column(db.String(100), nullable=False, unique=True) categories = db.Table( 'categories', db.Column('merchant_id', db.Integer, db.ForeignKey('merchant.id')), db.Column('category_id', db.Integer, db.ForeignKey('category.id')) ) class Merchant(db.Model): __tablename__ = 'merchant' id = db.Column(db.Integer, primary_key=True) merchant_code = db.Column(db.String(255), nullable=False) categories = db.relationship('Category', secondary=categories, backref=db.backref('categories', lazy='dynamic'))
Form
The import part here isĀ coerce=int, as in value is integer
class MultiCheckboxField(SelectMultipleField): widget = widgets.ListWidget(prefix_label=False) option_widget = widgets.CheckboxInput() class WorkTypeForm(FlaskForm): categories = SelectMultipleField('Select Category', coerce=int, option_widget=widgets.CheckboxInput(), widget=widgets.ListWidget(prefix_label=False) ) submit = SubmitField('Update')
View
The checkbox true value is integer (category id), therefore we need to provided the integer list.
@login_required @merchant.route('/categories/<code>', methods = ['GET','POST']) def worktype(code=None, error=None): categories = Category.query.all() form = WorkTypeForm() form.categories.choices = [(c.id, c.name_en) for c in categories ] merchant = Merchant.query.filter(Merchant.merchant_code == code).first() if merchant is None: return render_template('404.html'), 404 if request.method == 'GET': if merchant.categories: # This is where you prepopulate form.categories.data = [(c.id) for c in merchant.categories] if form.validate_on_submit(): ..... // code omitted ..... return render_template('categories.html', form=form, error=error, code=code)
Html
<div class="table-responsive"> {% if form %} {{ wtf.quick_form(form) }} {% endif %} </div>
Flask – Prepopulate SelectMultipleField
Thank you. This was very insightful to find a solution to my problem.
My form affects multiple Models through relationships so I was using something along the lines of:
queryA = session….
queryB = session….
form = myForm(obj=queryA, field_name_not_in_queryA=queryB.fieldName, fieldName_with_multiple_choices=?)
All the fields in my form were being pre-populated except the one that required multiple choices.
I just added this (coming from your example)
queryC = session…
form.field_name_with_multiple_choices.data = [(choice.name) for choice in queryC]