I have a form where users can dynamically add fields to it. While submitting this form, backend only sees the fields which backend generated
#forms.py
class ExpensesForm(FlaskForm):
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')
])
I'm passing this form with
return render_template('index.html', form=form, ...)
from the main.py
to index.html
All 4 fields are generated via;
<form class="form-horizontal" id="main-form" enctype=multipart/form-data role="form" method="post" action="/">
<input type="hidden" name="count" value="1"/>
{{ form.csrf_token }}
{{ form.expense_name(placeholder="Expense Name", id="expense_1", value="") }}
{{ form.cost(placeholder="Cost", id="cost_1", class="cost", value="") }}
{{ form.due_date(id="due_date_1") }}
{{ form.type(placeholder="Type", id="type_1") }}
<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>
A JQuery snippet generates the same fields with different(unique) id's after each button press as a row of new fields after the last #type_
id.
When I hit the submit button, the backend only receives the first row not the generated ones.
What am I missing here?
UPDATE:
# main.py
@main_blueprint.route('/', methods=['GET', 'POST'])
def index():
dates = []
form = ExpensesForm(request.form)
if request.method == 'POST':
print(form.data)
# prints the following even when the browser sends more than 1 set of data:
# {'due_date': None, 'csrf_token': long_hash, 'expense_name': 'Electric', 'cost': 13.0, 'type': 'mutual'}
if form.validate_on_submit():
for n in range(len(form.expense_name.data)):
if form.expense_name.raw_data[n] != '':
data = Expenses(form.expense_name.raw_data[n].title(),
form.cost.raw_data[n],
datetime.datetime.strptime(form.due_date.raw_data[n], '%Y-%m-%d').date(),
form.type.raw_data[n].title(),
)
print(data)
db.session.add(data)
db.session.commit()
return redirect(url_for('main.index'))
expenses = db.session.query(Expenses).all()
# expenses_schema = ExpensesSchema()
# output = expenses_schema.dump(expenses).data
output = []
for i in expenses:
output.append(i.__dict__)
return render_template('index.html', form=form, expenses=output)
UPDATE 2
Since form.data
is a dict I can't have the names matching with the new fields. But even if I give unique names to the added fields the backend only displays the initial form fields with print(form.data)
but if I do;
for k, v in request.form.items():
print(k, v)
I get all the fields. Doesn't seem the right way to me. Any thoughts?