Flask WTForms:为什么我上传文件的POST请求没有发送文件数据? [英] Flask WTForms: Why is my POST request to upload a file not sending the file data?

查看:107
本文介绍了Flask WTForms:为什么我上传文件的POST请求没有发送文件数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作一个上载文件的表单,但是文件数据未随请求一起发送.我正在手动导航到我的文件并单击提交".我的FileRequired验证程序失败. (如果我不包含它,则form.scan_file上的data字段为空.)

I am trying to make a form to upload a file, but the file data is not being sent with the request. I'm manually navigating to my file and hitting submit. My FileRequired validator fails. (And if I don't include it the data field on form.scan_file is empty.)

这是我的表格:

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 %}

看起来我犯的错误与.我究竟做错了什么?

It doesn't look like I'm making the same mistake as this person. What am I doing wrong?

自发布以来,我发现

Since posting, I have found this question, but on working through the offered solutions, none seem relevant to my situation.

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

EDIT 2: At one point, I printed request.files in the Werkzeug debugger and it was an empty dict. I can't reconstruct exactly what I did to get that result. Since then, I've inserted some print statements and in fact, request.files has my file object. So I have a way to retrieve my file. But I am supposed to be able to retrieve my file object at form.scan_file.data (see here). Right now this evaluates to None. More specifically, form.scan_file.has_file() evaluates to False. form.data evaluates to {'scan_file': None, 'csrf_token': <long-random-string> }

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

Even if I have another way of retrieving my file object, a consequence of this problem is that validation isn't working. My form doesn't pass the FileRequired() validation.

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

EDIT 3: With my new understanding of my problem, I see that it's similar to this question. However, it's at least apparently not duplicative because none of form = ScanForm(request.form), form = ScanForm(), or form = ScanForm(CombinedMultiDict((request.files, request.form))) make any difference to the behavior outlined in Edit 2.

推荐答案

首先,检查您的数据是否在该路由上被发布.其次,我认为您不需要将request.form传递给ScanForm,您只需要实例化它即可:

First of all, check if your data gets posted on that route. Second, I think you don't need to pass request.form to ScanForm, you just need to instantiate it like:

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

要检查通过表单而不是表单发布的内容

To check what gets posted with form, instead of

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" )

Lastly, you can render input file with {{scan_form.scan_file }} or <input type="file" name="scan_file"> (name attribute of input element should be equal to "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))

这篇关于Flask WTForms:为什么我上传文件的POST请求没有发送文件数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆