Flask WTForms:为什么我的 POST 上传文件请求没有发送文件数据?
Flask WTForms: Why is my POST request to upload a file not sending the file data?
我正在尝试制作一个表格来上传文件,但文件数据没有随请求一起发送。我正在手动导航到我的文件并点击提交。我的 FileRequired 验证器失败。 (如果我不包含它,form.scan_file
上的 data
字段为空。)
这是我的表格:
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 question,但在处理提供的解决方案时,none 似乎与我的情况相关。
编辑 2:有一次,我在 Werkzeug 调试器中打印了 request.files,它是一个空字典。我无法准确地重建我为获得该结果所做的工作。从那时起,我插入了一些打印语句,事实上,request.files
有我的文件对象。所以我有办法检索我的文件。但我应该能够在 form.scan_file.data
检索我的文件对象(参见 here)。现在这计算为 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)))
中的 none 对编辑 2 中概述的行为有任何影响。
首先,检查您的数据是否在该路线上发布。其次,我认为你不需要将 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属性应该等于"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))
我正在尝试制作一个表格来上传文件,但文件数据没有随请求一起发送。我正在手动导航到我的文件并点击提交。我的 FileRequired 验证器失败。 (如果我不包含它,form.scan_file
上的 data
字段为空。)
这是我的表格:
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 question,但在处理提供的解决方案时,none 似乎与我的情况相关。
编辑 2:有一次,我在 Werkzeug 调试器中打印了 request.files,它是一个空字典。我无法准确地重建我为获得该结果所做的工作。从那时起,我插入了一些打印语句,事实上,request.files
有我的文件对象。所以我有办法检索我的文件。但我应该能够在 form.scan_file.data
检索我的文件对象(参见 here)。现在这计算为 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)))
中的 none 对编辑 2 中概述的行为有任何影响。
首先,检查您的数据是否在该路线上发布。其次,我认为你不需要将 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属性应该等于"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))