Flask WTForms:为什么我上传文件的POST请求没有发送文件数据? [英] Flask WTForms: Why is my POST request to upload a file not sending the file data?
问题描述
我正在尝试制作一个上载文件的表单,但是文件数据未随请求一起发送.我正在手动导航到我的文件并单击提交".我的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屋!