Question

I'm trying to get file uploads with flask-uploads working and running in to some snags. I'll show you my flask view function, the html and hopefully someone can point out what I'm missing.

Basically what happens is that I submit the form and it fails the if request.method == 'POST' and form.validate(): check in the view function. It jumps down to display the template. wtforms isn't kicking me any errors on the form so I'm wondering why its failing that if statement.

What am I over looking?

Setting up flask-uploads:

# Flask-Uploads
photos = UploadSet('photos',  IMAGES)
configure_uploads(app, (photos))

View:

def backend_uploadphoto():
    from Application import photos
    from Application.forms.backend import AddPhotoForm

    clients = Client.query.all()
    events = Event.query.order_by('date').all()

    form = AddPhotoForm(request.form, csrf_enabled=True)

    if request.method == 'POST' and form.validate():
        from uuid import uuid4

        uuid = uuid4()
        filename = '{0}.jpg'.format(uuid)

        photo = Photo(uid=uuid, client=request.form['client'], event=request.form['event'])

        photofile = photos.save(request.files.get('photo'), photo.filename)

        return redirect(url_for('backend'))

    return render_template('backend/addphoto.html', form=form, clients=clients, events=events)

Form:

class AddPhotoForm(Form):
    photo = FileField('Photo')
    client = IntegerField('Client:')
    event = IntegerField('Event:')

HTML:

<form action="{{url_for('backend_uploadphoto')}}" method="post">
        <p>
            {{form.client.label}}
            <select name="client">
                {% for client in clients %}
                <option value="{{client.id}}">{{client.fullname}}</option>
                {% endfor %}
            </select>
            {{form.client.errors}}
        </p>

        <p>
            {{form.event.label}}
            <select name="event">
                {% for event in events %}
                <option value="{{event.id}}">{{event.name}}</option>
                {% endfor %}
            </select>
            {{form.event.errors}}
        </p>

        <p><label for="photo">Photo:</label>{{form.photo}} <input type="submit" value="Upload"> {{form.photo.errors}}</p>
    </form>
Was it helpful?

Solution

You have csrf_enabled=True but your form doesn't have any CSRF protection since you aren't inheriting from SecureForm. If you want to enable CSRF, read the documentation and update your form definition.

If this was unintended, you can remove csrf_enabled=True and your logic will work as expected.

To enable CSRF protection, there are a few steps:

  1. Inherit from SecureForm
  2. Create the generate_csrf_token and validate_csrf_token methods in your form. These methods will generate a unique key and raise errors when it doesn't validate.
  3. Add {{ form.csrf_token }} to your template.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top