Flask WTForms:为什么我上传文件的POST请求没有发送文件数据?

时间:2018-10-19 19:53:45

标签: flask flask-wtforms wtforms

我正在尝试制作一个上载文件的表单,但是文件数据未随请求一起发送。我正在手动导航到我的文件并点击提交。我的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 %}

看起来我犯的错误与this person相同。我究竟做错了什么?

编辑:自发布以来,我发现了this question,但是在研究提供的解决方案时,似乎都与我的情况无关。

编辑2:有一次,我在Werkzeug调试器中打印了request.files,这是一个空的字典。我无法完全重建为获得该结果所做的一切。从那时起,我插入了一些打印语句,实际上request.files有我的文件对象。因此,我有一种方法来检索我的文件。但是我应该能够在form.scan_file.data处检索我的文件对象(请参见here)。目前,该结果的值为None。更具体地说,form.scan_file.has_file()的值为Falseform.data的值为{'scan_file': None, 'csrf_token': <long-random-string> }

即使我有另一种检索文件对象的方法,此问题的结果也是验证不起作用。我的表单未通过FileRequired()验证。

编辑3:通过对问题的新理解,我发现它类似于此question。但是,它至少显然不是重复的,因为form = ScanForm(request.form)form = ScanForm()form = ScanForm(CombinedMultiDict((request.files, request.form)))都没有对Edit 2中概述的行为产生任何影响。

1 个答案:

答案 0 :(得分:3)

首先,检查您的数据是否在该路由上获得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"> (输入元素的名称属性应等于“ 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))