Rocket Pingu
Rocket Pingu

Reputation: 621

Post Rows of Inputs from a Form as Objects using Flask?

I have this form form where each row represents an object filled with inputs.

Here's the snippet of the form:

<form>
<li>
    <select name="network[][layer_type]"><!-- options here --></select>
    <input type="number" name="network[][num_filters]">
    <!-- other parameters here -->
</li>
<li>
    <select name="network[][layer_type]"><!-- options here --></select>
    <input type="number" name="network[][pool_size]">
    <!-- other parameters here -->
</li>
<li>
    <select name="network[][layer_type]"><!-- options here --></select>
    <input type="number" name="network[][num_filters]">
    <!-- other parameters here -->
</li>
</form>

On submitting, I want the output dict to be like this:

{
"network":[
    {"layer_type": "conv2d", "num_filters": 16, "kernel_size": 2, "padding": "valid", "stride": 2},
    {"layer_type": "max_pool2d", "num_filters": 16, "kernel_size": 2, "padding": "valid", "stride": 2},
    {"layer_type": "conv2d", "num_filters": 32, "kernel_size": 3, "padding": "valid", "stride": 2}       
  ]
}

Using request.form.getlist('network[]') returns []. How do I get that output dict using Flask?

Upvotes: 1

Views: 787

Answers (1)

Logan Bertram
Logan Bertram

Reputation: 1942

There seems to be a fundamental misunderstanding about flask and the relationship between your code and your templates. First of all, you can't drop code into your HTML template without using Jinja (Flask standard) or some other tool. Using Jinja you can add variables into your HTML template with {{variable}} and add limited logic into your template with {% for item in list %} HTML to loop {% endfor%}. More about Jinja conventions here and here.

Presuming you want the users to use your select and inputs to set layer type and number of filters and that the other details are set in similar fasshion, you will want your template to look like this:

<form>
<li>
    <select name="net1_layer_type_1"><!-- options here --></select>
    <input type="number" name="net1_num_filters_1">
    <!-- other parameters here -->
</li>
<li>
    <select name="net1_layer_type_2"><!-- options here --></select>
    <input type="number" name="net1_num_filters_2">
    <!-- other parameters here -->
</li>
<li>
    <select name="net1_layer_type_3"><!-- options here --></select>
    <input type="number" name="net1_num_filters_3">
    <!-- other parameters here -->
</li>
</form>

Then in your corresponding flask route, you can build this dictionary like this:

networks = {}
networks['network'] = []
networks['network'][0] = {'layer_type': request.form['net1_layer_type_1'], 'num_filters': request.form['net1_num_filters_1'], "kernel_size": 2, "padding": "valid", "stride": 2}

Repeat for the other items.

Using this as a basis, I'm sure you can see how you can make this more dynamic, allowing additional networks with additional members, and using loops to create each network member. Let's say you want to make 4 networks each with 5 memebers, on the route that renders your form, you create the lists "network_count" and "member_count" which look like [1,2,3,4] and [1,2,3,4,5], respectively. Then on your template use a loop to build your form that looks like this:

<form>
    {% for net in network_count %}
        {% for mem in member_count %}
            <li>
                <select name="net{{net}}_layer_type_{{member}}"><!-- options here --></select>
                <input type="number" name="net{{net}}_num_filters_{{member}}">
                <!-- other parameters here -->
            </li>
        {% endfor %}
    {% endfor %}
</form>

Use the same python as before to process, but loop that as well.

Upvotes: 1

Related Questions