Flask 在第一次验证时不知道动态添加的输入字段
Flask not aware of dynamically added input fields on first validation
如果用户单击它,我将通过按钮动态添加新的文件上传字段。
验证仅在每隔一次尝试时通过,那是因为 flask/wtforms 不知道新动态创建的输入字段。每当我点击我的提交按钮时,它只会警告第一个字段文件丢失。
一旦我放入所有必需的文件并提交,第一次尝试失败,但之后字段列表已初始化为所需的大小,下次我提交相同数量的文件时它可以工作。
forms.py
class ChildForm(FlaskForm):
class Meta:
csrf = False
childvalue1= IntegerField(default=1, validators=[DataRequired()])
childvalue2= FileField(validators=[FileRequired(),FileAllowed(['mp3'])])
class ParentForm(FlaskForm):
parentvalue1= FileField('PDF File', validators=[FileRequired(), FileAllowed(['pdf'])])
parentfieldlist= FieldList(FormField(ChildForm), min_entries=1)
submit = SubmitField('Upload')
html 文件
<form action="" method="post" enctype="multipart/form-data">
{{ form.hidden_tag() }}
<!-- PDF Upload -->
<div>
<label class="label">{{ form.parentvalue1.label }}</label>
{{ form.parentvalue1}}
<br>
</div>
<!-- Audio Upload -->
<br>
<div>
<label class="label">{{ form.parentfieldlist.label }}</label>
<table id="audiotable">
{% for entry in form.parentfieldlist%}
<tr>
{% for subfield in entry %}
<td>{{ subfield }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
</div>
<br>
<button type='button' class="add_more">Add More Files</button>
<br><br>
<p> {{ form.submit(class='button is-link') }}
</form>
JS 创建更多输入字段
<script>
String.format = function () {
var s = arguments[0];
for (var i = 0; i < arguments.length - 1; i++) {
var reg = new RegExp("\{" + i + "\}", "gm");
s = s.replace(reg, arguments[i + 1]);
}
return s;
}
var fieldNum = 1;
$('.add_more').click(function (e) {
e.preventDefault()
var firstTag = "parentfieldlist-" + fieldNum + "-childvalue1"
var secondTag = "parentfieldlist-" + fieldNum + "-childvalue2"
var rowTemplate = `<tr><td><input type='text' id=${firstTag } name=${firstTag } value=${fieldNum + 1} /></td>
<td><input type='file' id=${secondTag } name=${secondTag }/></td></tr>`;
$("#audiotable").append(rowTemplate);
fieldNum++;
});
</script>
有人碰巧知道如何让它工作吗?
另一个例子。如果我添加第二个上传字段并提交,这就是我的函数打印的内容:
[{'childvalue1': 1, 'childvalue2': <FileStorage: 'somefile.mp3' ('audio/mpeg')>}, {'childvalue1': 2, 'childvalue2': None}]
如果我再做一次并提交,就可以了。
在您使用 append_entry() 的地方,有一些 ajax 调用 python 函数的 hacky 解决方案,但我不相信这些并且不确定它们是否真的解决了问题。本质上,文件在第一次提交时总是 none
编辑:如果我从子值 2 中删除 'FileRequired',它根本不起作用。这是一张图片来说明我的意思
表单不知道我通过按钮添加的第二个上传字段
感谢您的任何建议
答案非常简单,但对我来说不是那么明显。
<input type='file' id=${secondTag } name=${secondTag }/>
需要这样,就像第一个childvalue一样,因为它有默认值所以我输入了
<input type='file' id=${secondTag } name=${secondTag } value=""/>
现在 Flask 可以识别 submit/validation 上动态添加的文件。从一开始就应该很明显,因为第一个值一直在传输,但是第二个值是'none',唯一的区别是两者之间的“值”
如果用户单击它,我将通过按钮动态添加新的文件上传字段。 验证仅在每隔一次尝试时通过,那是因为 flask/wtforms 不知道新动态创建的输入字段。每当我点击我的提交按钮时,它只会警告第一个字段文件丢失。
一旦我放入所有必需的文件并提交,第一次尝试失败,但之后字段列表已初始化为所需的大小,下次我提交相同数量的文件时它可以工作。
forms.py
class ChildForm(FlaskForm):
class Meta:
csrf = False
childvalue1= IntegerField(default=1, validators=[DataRequired()])
childvalue2= FileField(validators=[FileRequired(),FileAllowed(['mp3'])])
class ParentForm(FlaskForm):
parentvalue1= FileField('PDF File', validators=[FileRequired(), FileAllowed(['pdf'])])
parentfieldlist= FieldList(FormField(ChildForm), min_entries=1)
submit = SubmitField('Upload')
html 文件
<form action="" method="post" enctype="multipart/form-data">
{{ form.hidden_tag() }}
<!-- PDF Upload -->
<div>
<label class="label">{{ form.parentvalue1.label }}</label>
{{ form.parentvalue1}}
<br>
</div>
<!-- Audio Upload -->
<br>
<div>
<label class="label">{{ form.parentfieldlist.label }}</label>
<table id="audiotable">
{% for entry in form.parentfieldlist%}
<tr>
{% for subfield in entry %}
<td>{{ subfield }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
</div>
<br>
<button type='button' class="add_more">Add More Files</button>
<br><br>
<p> {{ form.submit(class='button is-link') }}
</form>
JS 创建更多输入字段
<script>
String.format = function () {
var s = arguments[0];
for (var i = 0; i < arguments.length - 1; i++) {
var reg = new RegExp("\{" + i + "\}", "gm");
s = s.replace(reg, arguments[i + 1]);
}
return s;
}
var fieldNum = 1;
$('.add_more').click(function (e) {
e.preventDefault()
var firstTag = "parentfieldlist-" + fieldNum + "-childvalue1"
var secondTag = "parentfieldlist-" + fieldNum + "-childvalue2"
var rowTemplate = `<tr><td><input type='text' id=${firstTag } name=${firstTag } value=${fieldNum + 1} /></td>
<td><input type='file' id=${secondTag } name=${secondTag }/></td></tr>`;
$("#audiotable").append(rowTemplate);
fieldNum++;
});
</script>
有人碰巧知道如何让它工作吗? 另一个例子。如果我添加第二个上传字段并提交,这就是我的函数打印的内容:
[{'childvalue1': 1, 'childvalue2': <FileStorage: 'somefile.mp3' ('audio/mpeg')>}, {'childvalue1': 2, 'childvalue2': None}]
如果我再做一次并提交,就可以了。 在您使用 append_entry() 的地方,有一些 ajax 调用 python 函数的 hacky 解决方案,但我不相信这些并且不确定它们是否真的解决了问题。本质上,文件在第一次提交时总是 none
编辑:如果我从子值 2 中删除 'FileRequired',它根本不起作用。这是一张图片来说明我的意思
表单不知道我通过按钮添加的第二个上传字段 感谢您的任何建议
答案非常简单,但对我来说不是那么明显。
<input type='file' id=${secondTag } name=${secondTag }/>
需要这样,就像第一个childvalue一样,因为它有默认值所以我输入了
<input type='file' id=${secondTag } name=${secondTag } value=""/>
现在 Flask 可以识别 submit/validation 上动态添加的文件。从一开始就应该很明显,因为第一个值一直在传输,但是第二个值是'none',唯一的区别是两者之间的“值”