Flask WTForms QuerySelectField does not work with BS4 Bootstrap-selectpicker.js (bootstrap-select v1.13.1)

34 views Asked by At

Everything on the WTForm works correctly and I've searched many WTForms QuerySelectedField questions here as well.

My form presents all records as it should correctly except for this "Country" pull-down QuerySelectedField form tool, which doesn't show the correct country name.

This form should have presented "Canada" because the user.country database field contains Canada's country_id = 123 and not Afghanistan's 115. Afghanistan is just the top/first record of the select list.

enter image description here

I'm sure it's a small and obvious problem, but I can't see a solution (other than a bug) and I hope someone out there has fixed this problem already.

WTForms is version 2.3.3

WTForms-SQLAlchemy is version 0.2

forms.py

class UserDetailForm(FlaskForm):
    username = StringField('Username', id='username' , validators=[DataRequired()])
    country = QuerySelectField(query_factory=lambda: Country.query.filter(Country.region!="Aggregates"), get_pk=lambda x: x.id, get_label="name")

Form.html

{{ form.country(class="selectpicker", value = current_user.country) }}

The Network view in Chrome Inspect tool shows that the form calls:

<select class="selectpicker" id="country" name="country" value="123"><option value="115">Afghanistan</option><option value="123">Canada</option></select>

Models.py

class User(db.Model, UserMixin):

    __tablename__ = 'User'

    id = Column(Integer, primary_key=True, autoincrement=True)
    username = Column(String(22), primary_key=True, unique=True)
    country = Column(Integer) 

    def __init__(self, **kwargs):
        for property, value in kwargs.items():
            if hasattr(value, '__iter__') and not isinstance(value, str):
                value = value[0]
            if property == 'password':
                value = hash_pass( value ) # we need bytes here (not plain str)                
            setattr(self, property, value)

    def __repr__(self):
        return str(self.username)

Routes.py

@blueprint.route('/profile', methods=['GET', 'POST'])
@login_required
def profile():
    # user_detail_form = UserDetailForm(request.form)
    form = UserDetailForm(request.form)

    if 'profile' in request.form:
         ...
         return render_template('page-user.html', msg='Profile changes made', form=form)
         ## This works correctly!

    else:

        sidetog = 'profile'
        # return render_template('page-user.html', value=sidetog, form=user_detail_form)
        return render_template('page-user.html', value=sidetog, form=form)
        
        ## This works correctly also, for everything except the country pull-down value

Data All country code ids here are integers.

country.name          country.id
 Canada              123
 Afghanistan         115

user.country
123 
0

There are 0 answers