Flask Python - validate_on_submit() not evaluating True

Hello Everybody,

Bit lost as to why “if formIncident.validate_on_submit():” isn’t evaluating True? as you can see from the console output below formIncident.validate_on_submit(): valuates “True” and yet it wont execute the block of code but jumps right to the following else to complete the execution.

No errors appear anywhere.

What am I missing?

Any assistance you can provide would be greatly appreciated :slight_smile:

@incidentBP.route('/incident', methods = ['GET', 'POST']) 
def incident():        
    formIncident = IncidentForm()       
    if request.method == 'POST':        
        print(f"Value return from btn click =>:, {formIncident.btn_submitIncident.data}") 
        print(f"Button value type:=>:, {type(formIncident.btn_submitIncident.data)}")    
        if formIncident.validate_on_submit(): 
             //not executing the block of code on True valuation
            //code keeps jumping to the else to complete the execution

Part of the form more specifically the submit component

class IncidentForm(FlaskForm):
    versionSelect = SelectField('Version', coerce=int, choices=[])
    btn_submitIncident = SubmitField(label="Create Incident")

HTML part of the script / the submit button

<form method="POST" action="" novalidate>
    {{ form.csrf_token }}
    {{ form.hidden_tag() }}

    {{ form.btn_submitIncident(class="w-100 btn btn-primary btn-lg") }}    

Console output from above code
print(f"Value return from btn click =>:, {formIncident.btn_submitIncident.data}“)
print(f"Button value type:=>:, {type(formIncident.btn_submitIncident.data)}”)

* Debugger PIN: 366-622-259
Value return from btn click =>:, True
Button value type:=>:, <class 'bool'> - - [18/Mar/2023 20:31:36] "POST /incident HTTP/1.1" 200 -

dont you need to specify some choices there? If the choice isnt in the choices field, that would be a validation fail…

1 Like

Hi @robin01, does the form actually validate? You might print(formIncident.errors) for further diagnosis… BTW the request.method == 'POST' check is redundant here, validate_on_submit() does this anyway:


Hi M_hutley,

Your right, the problem was round the version dropdown select field. Having said that, the version field is populated based on the project dropdown; using javascrip, select but not sure why the script isn’t seeing the selection.

the only think i can think of is the way im populating the version field.

 projectSelect = SelectField('Project', coerce=int, 
     choices=[(prj.prj_index, prj.prj_name) for prj in dbQueryProject])    
    versionSelect = SelectField('Version', coerce=int, choices=[])
    btn_submitIncident = SubmitField(label="Create Incident")

Hi m3g4p0p,

Took your suggestion and inserted the print(f"formInc err =>: {formIncident.errors} and sure enough the problem was the way version is loaded. version field is populated based on the project select field so its calling a Javascript to populate the version field.

Image, version field is populating:

Javascrip - version field populated based on project field

let project_selection = document.getElementById('projectSelect');
let version_selection = document.getElementById('versionSelect');
project_selection.onchange = function() {
	projectValue = project_selection.value;				
	fetch('/gVersion/' + projectValue).then(function(response) { 					
	    response.json().then(function(data) {						
		let optionHTML = '';
			for(let ver of data.versionsArray) {
				optionHTML += '<option value="' + ver.ver_projectid + '">' +
                                 ver.ver_version + '</option>';														
			version_selection.innerHTML = optionHTML;						 

Yeah, i’m pretty sure that’s the wrong way to load options to a field you’re trying to validate…

I should say, it needs to go through the python at some point to add the options to the choices array of the object. It’s the right way to construct the javascript side of things.

you could… add a route to your form for setting the values, for example. That route would need to take in the (probably json) input and parse it down into a set of objects (projectid,projectversion) (? I dont know what you want to use there), and then assign the array of objects to the choices (versionSelect.choices = myInputArray)

And i’ll get a bunch of people screaming at me that that is a massive security hole because you’re not sanitizing the input from the user. Which is a fair criticism.

If you look at this video: (which… you may have already done based on your variable names…)

You’ll see he feeds the state name into the route to get the values out to create the javascript fields. Similar concept, but need to add the step of putting together the choices attribute for the SelectField.

Since this is just the path you’re passing to the fecth()call… if it’s an internal route, don’t you have access to that resource directly, so you might populate the options on the server side and don’t need the AJAX round trip in the first place?

PS: Also note that a value like 0.4.1 can’t get coerced to int as per your field declaration, so this field will never validate.

Depends on how he wants to load it. It looks like a dependent call (based on Project, pull versions), so there will need to be an AJAX loop, it just needs to feed through Python properly.

Ah true, didn’t read properly. ^^ Yes for such dynamic field values you’ll need AJAX.

1 Like

I hadnt noticed the fetch was already internal, so both of us misread ^^

If that fetch is part of the form class, you’re already 90% of the way there. Just use that fetch’s route to stuff the SelectField’s choices.

1 Like

Okay just gave it a try… populating the field with JS shouldn’t be a problem per se, however you need to set validate_choice=False then since those dynamic choices are not known to the form (you may write a custom validator though). And remove that int coercion as mentioned above.