Вы можете иметь только один результат формы для каждой отправки формы. Чтобы иметь возможность подавать произвольное и неизвестное количество входных данных, вам необходимо реструктурировать форму с помощью WTForm полевых приложений .
forms.py
from flask_wtf import FlaskForm
from wtforms import (
FieldList, FormField, DateField FloatField, StringField, SelectField)
from wtforms import Form as NoCsrfForm
class ExpenseItem(NoCsrfForm):
expense_name = StringField('Expense_Item', validators=[DataRequired()])
cost = FloatField('Cost', validators=[DataRequired()])
due_date = DateField('Due Date', format='%Y-%m-%d',
validators=[DataRequired()],
default=datetime.datetime.today().date())
type = SelectField('Role', choices=[
('mutual', 'Mutual'),
('personal#1', 'Personal #1'),
('personal#2', 'Personal #2'),
])
class ExpensesForm(FlaskForm):
"""A collection of expense items."""
items = FieldList(FormField(ExpenseItem), min_entries=1)
Я настоятельно рекомендую вам предвосхитить все имена ваших полей с expense
, а не просто expense_name
ради здравомыслия.
index.html
<form class="form-horizontal" id="main-form" enctype=multipart/form-data role="form" method="post" action="/">
<input type="hidden" name="count" value="1"/>
{{ form.hidden_tag() }}
{% for expense_item in form.items %}
{{ form.expense_name(placeholder="Expense Name", value="") }}
{{ form.cost(placeholder="Cost", class="cost", value="") }}
{{ form.due_date() }}
{{ form.type(placeholder="Type") }}
{% endfor %}
<button id="b1" class="btn btn-info add-more" type="button">+</button>
<small>Press + to add another set of fields.</small>
<br>
<hr>
<button class="btn btn-sm btn-success" type="submit">Post Expense</button>
</form>
Обратите внимание, что атрибут id
полей ввода HTML должен соответствовать определенному шаблону. Таким образом, для каждого нового поля статьи расходов, которое вы добавляете, нажимая кнопку +
, необходимо изменить нумерацию атрибута id
его полей ввода.
something.js
Все остальное было сравнительно легко. Теперь вам нужно написать фрагмент .js, который будет переиндексировать атрибуты id
всех полей ввода каждый раз, когда добавляется новая статья расходов. Я сделал это, используя библиотеку Zepto для Javascript. Это было не весело, а мой .js ужасен. Лучшее, что я могу здесь сделать, это просто вставить все это и надеяться, что оно будет вам полезно. Я знаю, что это сбивает с толку, но я добавил несколько классов в курс . Для вас вам понадобится расход_элемент / расход_запрос или все, что вы пошли с:
// append class-box when new class link clicked
$("#new-class").click(function(event) {
appendClassBox('#classes', {{ newclass|tojson|safe }});
reindexNames('.class-box');
return false;
})
// remove class box when its "remove" link is clicked
$(document).on('click', '#remove-class', function(){
var $toremove = $(this).closest('.class-box');
$toremove.remove();
reindexNames('.class-box');
return false;
})
// add a new class-box
function appendClassBox(container, content) {
$(container).append(content);
// raise last and hence newest class box
raiseClassBox($(container).children().last())
return false;
}
function isNormalInteger(str) {
var n = ~~Number(str);
return String(n) === str && n >= 0;
}
// re-index class-box names
function reindexNames(class_name) {
var $oboxen = $(class_name);
$oboxen.each(function(index) {
// Get all the input fields in the class-box.
var $labels = $oboxen.eq(index).find('label')
var $inputs = $oboxen.eq(index).find(
'input, select, textarea')
// Update the index contained in the name attribute.
$inputs.each(function(idx) {
var $name = $inputs.eq(idx).attr('name').split('-');
// If number in name, grab from number onwards.
var $has_num = false
for (var part in $name) {
if (isNormalInteger($name[part])) {
$has_num = true
$name = $name.slice(part)
$name[0] = index
break
}
}
// Re-index.
if ($has_num == false) {
$name.unshift(index)
}
var $prefix = 'questions'
if (class_name == '.class-box') {
$prefix = 'classes'
}
$name.unshift($prefix)
if (idx > 0) {
$labels.eq(idx - 1).attr('for', $name.join('-'));
}
$inputs.eq(idx).attr('id', $name.join('-'));
$inputs.eq(idx).attr('name', $name.join('-'));
})
})
}
views.py
@main_blueprint.route('/', methods=['GET', 'POST'])
def index():
form = ExpensesForm()
# Iterate over a collection of new expense items.
if form.validate_on_submit():
for item in form.items.data:
print(item['expense_name'])
print(item['cost'])
print(item['due_date'])
print(item['type'])