Flask WTForms: почему мой POST-запрос на загрузку файла не отправляет данные файла? - PullRequest
0 голосов
/ 19 октября 2018

Я пытаюсь создать форму для загрузки файла, но данные файла не отправляются с запросом.Я вручную перехожу к своему файлу и нажимаю "Отправить".Мой валидатор FileRequired не работает.(И если я не включу его, поле data в form.scan_file будет пустым.)

Вот моя форма:

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

class ScanForm(FlaskForm):
    scan_file = FileField(validators=[FileAllowed(['nii', 'nii.gz', 'zip']), FileRequired()])

Вот мои views.py:

from flask import Blueprint, render_template, request, flash, redirect, url_for, session
from .models import Scan
from .forms import ScanForm
from .service import ScanService
from cookiecutter_mbam.utils import flash_errors

blueprint = Blueprint('scan', __name__, url_prefix='/scans', static_folder='../static')

@blueprint.route('/add', methods=['GET', 'POST'])
def add():
    """Add a scan."""
    form = ScanForm(request.form)
    if form.validate_on_submit():
        f = form.scan_file.data
        service = ScanService()
        xnat_uri = service.upload(session['user_id'], session['curr_experiment'], f)
        Scan.create(xnat_uri=xnat_uri)
        flash('You successfully added a new scan.', 'success')
        return redirect(url_for('experiment.experiments'))
    else:
        flash_errors(form)
    return render_template('scans/upload.html',scan_form=form)

Вот мой upload.html:

{% extends "layout.html" %}

{% block content %}


<form method="POST" action="{{ url_for('scan.add') }}" enctype="multipart/form-data">
    {{ scan_form.csrf_token }}

    <input type="file" name="file">
    <input class="btn btn-primary" type="submit" value="Submit">

</form>

{% endblock %}

Не похоже, что я совершаю ту же ошибку, что и этот человек .Что я делаю неправильно?

РЕДАКТИРОВАТЬ: С момента публикации я нашел этот вопрос , но при работе с предлагаемыми решениями ни один из них не кажется подходящим для моей ситуации.

РЕДАКТИРОВАТЬ 2: В какой-то момент я напечатал request.files в отладчике Werkzeug, и это был пустой дикт.Я не могу восстановить точно, что я сделал, чтобы получить тот результат.С тех пор я вставил несколько операторов печати и на самом деле, request.files имеет мой файловый объект.Таким образом, у меня есть способ восстановить мой файл.Но я должен иметь возможность получить свой файловый объект на form.scan_file.data (см. здесь ).Прямо сейчас это оценивается в None.Более конкретно, form.scan_file.has_file() оценивается как False.form.data оценивается как {'scan_file': None, 'csrf_token': <long-random-string> }

Даже если у меня есть другой способ получения моего файлового объекта, следствием этой проблемы является то, что проверка не работает.Моя форма не проходит проверку FileRequired ().

РЕДАКТИРОВАТЬ 3: С моим новым пониманием моей проблемы, я вижу, что это похоже на этот вопрос .Однако это, по крайней мере, явно не дублирует, потому что ни один из form = ScanForm(request.form), form = ScanForm() или form = ScanForm(CombinedMultiDict((request.files, request.form))) не имеет никакого значения для поведения, описанного в Edit 2.

1 Ответ

0 голосов
/ 20 октября 2018

Прежде всего, проверьте, получает ли ваши данные запрос POST по этому маршруту.Во-вторых, я думаю, что вам не нужно передавать request.form в ScanForm, вам просто нужно создать его экземпляр, например:

def add():
    """Add a scan."""
    form = ScanForm()
    ...

Чтобы проверить, что публикуется в форме, вместо

if form.validate_on_submit():

вы можете использовать и распечатать form.scan_file.data

if form.is_submitted():
    print(form.scan_file.data)

Наконец, вы можете отобразить входной файл с помощью {{scan_form.scan_file}} или <input type="file" name="scan_file"> (атрибут name элемента input должен быть равен "scan_file")

Вот мой пример:

Форма:

class ArticleForm(FlaskForm):
    article_image = FileField('Article_image', validators=[FileRequired()])

Форма в шаблоне:

<form action="" method="post" enctype="multipart/form-data">
    {{ article_form.csrf_token }}
    {{ article_form.article_image }}
    <input type="submit" value="submit"/>
</form>

Контроллер (сохранение файла):

article_form = ArticleForm()

        if article_form.validate_on_submit():

            f = article_form.article_image.data
            name = current_user.username + "__" + f.filename
            name = secure_filename(name)
            f.save(os.path.join("./static/article_images/", name))
...