1

I can't work out why Wtforms is not preventing submission of the form when an error is detected. Instead of displaying the error message it submits the form and then I get a "TypeError: The view function did not return a valid response" because my "routes" code only has a return statement at the end of the validate_on_submit block. This means that the form is correctly detecting the validation error - but why is the form being submitted? Shouldn't this be prevented because of the validation error?

forms.py

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField, FloatField, SelectField, HiddenField, Form, FormField, FieldList
from wtforms.validators import DataRequired, Optional, InputRequired, ValidationError

class Vent_form(FlaskForm):

    hidden_id = HiddenField('Vent id')
    room_height = FloatField('Room height (m)',validators=[DataRequired()])
    air_change = FloatField('Air tightness @50Pa',validators=[DataRequired()])
    vent_type = SelectField('Ventilation type', validators=[DataRequired()], choices=['Natural','Extract only','Balanced'])
    mvhr = SelectField('MVHR unit', validators=[DataRequired()], choices=['None','Default'])
    vent_rate = FloatField('Purpose vent rate',validators=[DataRequired()])
    submit = SubmitField('Submit data')

routes.py

@app.route('/Ventilation', methods = ['GET', 'POST'])
def Vent_disp():
   
   if 'project_name' not in session:
      session['project_name'] = "0: No project selected"

   project_name = session['project_name'].split(':')[1]

   project_choices = [(str(c.id) + ': ' + c.project_name) for c in Peter.query.all()]  
   form2 = Which_project(project_choice = session['project_name'])
   form2.project_choice.choices = project_choices

   form_edit = Vent_form()

   if form2.submit.data:
      session['project_name'] = form2.project_choice.data
      project_name = session['project_name'].split(':')[1]

   return render_template('Ventilation.html', form_edit=form_edit, form2=form2, ventilation = Ventilation.query.filter_by(project_id=session['project_name'].split(':')[0]).all(), project_name=project_name)

@app.route('/Edit_vent', methods = ['GET', 'POST'])
def Edit_vent():

   form_edit = Vent_form()
   
   if form_edit.validate_on_submit():

      ventilation = Ventilation.query.get(form_edit.hidden_id.data)
      ventilation.room_height = form_edit.room_height.data
      ventilation.air_change = form_edit.air_change.data
      ventilation.vent_type = form_edit.vent_type.data
      ventilation.mvhr = form_edit.mvhr.data
      ventilation.vent_rate = form_edit.vent_rate.data

      db.session.commit()

      return redirect(url_for('Vent_disp'))

html:

<div class="modal-body">
    <form action = "{{ url_for('Edit_vent') }}" method = "post" novalidate>
        <div class="container-fluid">
        
        {{ form_edit.csrf_token }}
        {{ form_edit.hidden_id(value=row.id) }}
        <p>{{ form_edit.submit() }}</p>
        
            <div class="row">
                <div class="form-group col-sm-6">
                    {{ form_edit.room_height.label }}
                    {{ form_edit.room_height(class="form-control", value=row.room_height) }}
                    {% for error in form_edit.room_height.errors %}
                    <span style="color: red;">[{{ error }}]</span>
                    {% endfor %}

etc
3
  • Is the /Ventilation route important to your question? If not, I'd recommend removing it. Regarding your issue, 1) Are you sure you're hitting this code with a POST and not a GET? 2) not sure if this would help or not but perhaps try changing your validate_on_submit() to something like if request.method == 'POST' followed by if not form.validate(): That's how Commented Jan 16, 2021 at 19:51
  • Thanks @Ben, the /Ventilation route is returned to once form_edit has validated. The modal is on the form_edit route and the main page is on /ventilation. I've found some other references to this problem. It seems that Bootstrap will always close a modal when a submit button is pressed, regardless of whether there are errors, so I need some JS to keep the modal open if there are errors. Tried a number of examples given online but none are working for me! Might try simply flashing the messages on the main page "/ventilation" returned to on button submit. Not ideal, but a workaround. Commented Jan 16, 2021 at 20:08
  • Thank you, Sam. If you have a few minutes, it could be useful for future users if you would 'answer' your own question with what you've found. Commented Jan 16, 2021 at 20:20

1 Answer 1

1

I've found a number of similar questions on here with a similar issue. It seems that Boostrap automatically closes a Modal when the submit button is pressed regardless of whether there are errors reported through WTforms. To solve this requires some JavaScript / Jquery to keep the Modal open until the form is validated - tried a number of examples given elsewhere on Stack overflow - none have worked for me but this does seem to be what's required.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.