Search code examples
pythonflaskflask-wtformswtforms

wtforms/flask_wtf validator: FileAllowed, not catching forbidden file extensions


Observed Issue

I am trying to validate file extensions on a FileField field. The form successfully validates even when I pass files with extensions not included in the validator constructor. In this example I am using a test .pdf file which is not blank:

validators=[FileRequired(),FileAllowed(['jpg', 'png'], 'Images only!')]

form contents: data = <FileStorage: 'test.pdf' ('application/pdf')>
errors = ()

Code

route

from flask import Flask, render_template
from forms import ConsoleUploadForm

app.config['SECRET_KEY'] = 'superdupersecret'

@app.route("/")
@app.route("/home", methods=['GET', 'POST'])
def home():
    form = ConsoleUploadForm()  

    if form.validate_on_submit:
        # this is just my debug statement
        print(f"validated with -> {form.console_log_file.data} {form.console_log_file.errors}")

    return render_template("home.html", form=form)

form class

from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed, FileRequired

class ConsoleUploadForm(FlaskForm):
    console_log_file = FileField("Choose File...", render_kw={"class": "custom-file-input"}, validators=[
        FileRequired(), FileAllowed(['jpg', 'png'], 'Images only!')])

HTML

<html>
    <form method="POST" action="/home" enctype="multipart/form-data">
        {{ form.hidden_tag() }}
        <legend>Log Selection:</legend>
        <div class="form-row">
            <div class="form-group col-md-6">
                <label for="console_log_file">Console Log File</label>
                <div class="input-group mb-3">
                    <div class="custom-file">
                        {{ form.console_log_file(class="custom-file-input") }}
                        {{ form.console_log_file.label(class="custom-file-label") }}
                    </div>
                </div>
            </div>

            {% if form.console_log_file.errors %}
            <div class="invalid-feedback">
                {% for error in form.console_log_file.errors %}
                    <span>{{ error }}</span>
                {% endfor %}
            </div>
            {% endif %}

        </div>
    </form>
</html>

Desired Outcome

On pressing submit having passed a forbidden file extension type to the FileField I would expect to see elements in forms.console_log_file.errors and see them in my debug print statement.

What am I missing here?


Solution

  • This is a case of the handwritten typo... left out the parenthesis when trying to call the validate_on_submit method.

    route

    if form.validate_on_submit: ---becomes---> if form.validate_on_submit():