2
votes

I'm creating a series of form fields dynamically from database rows, each field will have it's own form. When a form is submitted it will update a row in the database. The problem I have is how do I match the submitted form up with the relevant row? All the form fields have the same name 'shared' but this should be ok as each field has it's own form.

views.py

def setting(nickname):
    user = User.query.filter_by(nickname = nickname).first()
    cars = user.cars.all()

    form_list = []
    for car in cars:
        class F(Form):
            pass
        setattr(F, 'shared', TextField(default=car.shared, label = car.carname))
        form = F(request.form, obj = car)
        form_list.append(form)

    if form.validate_on_submit():
        flash(request.form)
        flash(form.shared.data)

    return render_template('settings.html',
        user = user,
        form_list = form_list
    )

settings.html

{% for field in form_list %}
<form action="" method="post" name="share">
    {{ field.shared.label }} - {{ field.shared }}
    <input type="submit" value="share/make private"/>
</form>
{% endfor %}

Thanks

1

1 Answers

2
votes

You must create one form instead several (one form == one request).

For example you can create form class dynamicaly with shared_<CAR_ID> fields names:

def create_cars_form_class(cars):
    form_fields = {}
    for car in cars:
        field_id = 'shared_{}'.format(car.id)
        form_fields[field_id] = TextField(label=car.carname,
                                          default=car.shared)
    return type('CarsForm', (Form,), form_fields)

def settings(nickname):
    user = User.query.filter_by(nickname = nickname).first()
    cars = user.cars.all()
    CarsForm = create_cars_form_class(cars)

    if request.method == 'POST':
        shareform = CarsForm(request.form)
        if shareform.validate():
            for name, value in shareform.data.items():
                if not name.stratswith('shared_'):
                    continue
                car_id = name.lstrip('shared_')

                # update shared there
                update_car_shared(car_id, value)
    else:
        sharefrom = CarsForm()

    return render_template('settings.html',
        user = user,
        shareform = shareform,
    )

and

{% for name, field in shareform._fields.items() %}
    {% if name.startswith('shared_') %}
        {{ field.label }}: {{ field }}<br/>
    {% endif %}
{% endfor %}
<input type="submit" value="share/private"/>