我有一个水果表单,其中有一个FieldList对象用于香蕉:
bananas = FieldList(FormField(BananaForm))
在前端,最初,我将其中一个字段添加到FieldList中
form.append_entry()
现在我使用了JavaScript,成功创建了函数,可以动态地添加(加号按钮)或删除(减号按钮)可以填写信息的香蕉表单字段的数量。
FielstList会自动为其所有字段创建id。因此,为了使用js进行动态添加,我复制了HTML代码并设置了字段id + = 1,例如:
第一个字段:
<tr>
<td><input id="bananas-0-originCountry" type="text" /></td>
</tr>
重复的字段增加1:
<tr>
<td><input id="bananas-1-originCountry" type="text" /></td>
</tr>
当我按照以下方法命名字段并提交表单时,WTForms将自动在后端识别添加的字段(运行良好)。
到目前为止还不错,但这是我的问题: 为了使表单有效,我必须向每个WTForm添加CSRF字段。在Jinja模板中,我使用以下代码实现:
{{ form.hidden_tag() }}
然而,当我使用我的js函数复制HTML时,我会遗漏CSRF字段(因为在提交之前,后端表单对象不知道添加的FormFields)。那么我该如何动态生成这些CSRF字段呢?(使用Ajax请求吗?如果是,如何实现?)这应该是表单和flask的标准用例。希望我描述清楚了,如果没有,请让我知道。感谢任何帮助!更新:以下是我的代码
JS函数
function addBanana(){
// clone and insert banana node
var node = document.getElementById("fruitTable");
var trs = node.getElementsByTagName("tr");
var tr = trs[trs.length-2];
var tr2 = tr.cloneNode(true);
tr.parentNode.insertBefore(tr2, tr);
// in order to increment label and input field ids
function plusone(str){
return str.replace(
new RegExp("-(\\d+)-", "gi"),
function($0, $1){
var i = parseInt($1) + 1;
return "-" + i + "-";
}
);
}
// change inputs
var inputs = tr.getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++){
inputs[i].setAttribute("id", plusone(inputs[i].getAttribute("id")));
}
var minusbutton =
['<td>',
'<button class="btn" type="button" onClick="removeBanana()"><i class="icon-black icon-minus"></i></button>',
'</td>'
].join('\n');
// only append at the first add
// second add automatically copies minus button
if (trs.length < 6){
tr.innerHTML += minusbutton
}
}
function removeBanana(){
var node = document.getElementById("fruitTable");
var trs = node.getElementsByTagName("tr");
var tr = trs[trs.length-2];
var trParent = tr.parentNode;
trParent.removeChild(tr);
}
Jinja模板:
<form method="POST" action="newsubmit">
{{ form.hidden_tag() }}
<table id="fruitTable" class="table">
{{ render_field(form.description) }}
<tr><td><h3>Bananas</h3></td></tr>
{% set counter = 0 %}
{% for banana in form.bananas %}
<tr>
{{ banana.hidden_tag() }}
{% set counter = counter + 1%}
{% for field in banana if field.widget.input_type != 'hidden' %}
{{ render_field_oneline(field) }}
{% endfor %}
{% if counter > 1 %}
<td>
<button class="btn" type="button" onClick="removeBanana()"><i class="icon-black icon-minus"></i></button>
</td>
{% endif %}
</tr>
{% endfor %}
<tr><td></td><td><button class="btn" type="button" onClick="addBanana()"><i class="icon-black icon-plus"></i></button></td></tr>
</table>
<input class="btn btn-primary" style="margin-left:300px;"type="submit" value="Submit" />
</form>
Jinja模板宏:
{% macro render_field_oneline(field) %}
<td>{{ field.label }}</td>
<td>{{ field(**kwargs)|safe }}
{% if field.errors %}
<ul class=errors>
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</td>
{% endmacro %}
{% macro render_field(field) %}
<tr>
{{ render_field_oneline(field) }}
</tr>
{% endmacro %}
hidden_tag()
应该在复制的 <tr> 中呈现CSRF标签并被一起复制(这可能不是正确的方法,因为它将具有相同的哈希值),但实际上它甚至没有被复制!我真的不明白这里发生了什么神奇的事情。然而,我可以肯定地说CSRF标签没有被清除或替换! - kadrian