gerpaick
gerpaick

Reputation: 799

Django - how to get list of inputs, selects dynamically created with javascript?

I have a javascript code to create all combination of product based on characteristics that are added dynamically. HTML eesult of this script is:

<form id="myWizard" action="" method="post" role="form">    
<table>
        <tbody>
          <tr>
            <td>1</td>
            <td><select id="combination[0].product" name="combination[0].product">
              <option value="25">
                product_desc pc.10
              </option>
              <option value="26">
                product_desc pc.5
              </option>
              <option value="21">
                product_desc
              </option>
            </select></td>
            <td><input readonly="readonly" value="5.00" id="combination[0].price" name="combination[0].price" class="form-control" type="text" /></td>
            <td><input readonly="readonly" value="a" id="combination[0].color" name="combination[0].color" class="form-control" type="text" /></td>
            <td><input readonly="readonly" value="1" id="combination[0].quantity" name="combination[0].quantity" class="form-control" type="text" /></td>
          </tr>

          <tr>
            <td>2</td>
            <td><select id="combination[1].product" name="combination[1].product">
              <option value="25">
                product_desc pc.10
              </option>
              <option value="26">
                product_desc pc.5
              </option>
              <option value="21">
                product_desc
              </option>
            </select></td>
            <td><input readonly="readonly" value="5.00" id="combination[1].price" name="combination[1].price" class="form-control" type="text" /></td>
            <td><input readonly="readonly" value="a" id="combination[1].color" name="combination[1].color" class="form-control" type="text" /></td>
            <td><input readonly="readonly" value="5" id="combination[1].quantity" name="combination[1].quantity" class="form-control" type="text" /></td>
          </tr>

          <tr>
            <td>5</td>
            <td><select id="combination[8].product" name="combination[8].product">
              <option value="25">
                product_desc pc.10
              </option>
              <option value="26">
                product_desc pc.5
              </option>
              <option value="21">
                product_desc
              </option>
            </select></td>
            <td><input readonly="readonly" value="5.00" id="combination[8].price" name="combination[8].price" class="form-control" type="text" /></td>
            <td><input readonly="readonly" value="c" id="combination[8].color" name="combination[8].color" class="form-control" type="text" /></td>
            <td><input readonly="readonly" value="50" id="combination[8].quantity" name="combination[8].quantity" class="form-control" type="text" /></td>
          </tr>
        </tbody>
      </table> 
</form>

Of course there can be many more characteristics (for example type, material...).

How can I process it with request.POST? I tried getlist but without success. For the record I use Django 1.9. Is there any way I can get list of dictionaries from this request, so I would get something like:

list = [{'product_id': '25', 'price':'5.00', 'color':'c', 'quantity':'50'},
{'product_id': '26', 'price':'5.00', 'color':'a', 'quantity':'1'},
{'product_id': '21', 'price':'5.00', 'color':'a', 'quantity':'5'} 
]

or anything similiar?

Upvotes: 1

Views: 918

Answers (1)

user707650
user707650

Reputation:

One solution is to straightforwardly manipulate the POST data, for example like this:

results = defaultdict(dict)
for k, v in request.POST.items():
    _, no, key = re.split(r'\[(?P<no>\d+)\]\.', k, maxsplit=2)
    results[no][key] = v
data = []
for value in results.values():
    data.append(value)

The resulting data looks like (with the current table data):

[{'product': '25', 'price': '5.00', 'color': 'a', 'quantity': '1'}, 
 {'product': '25', 'price': '5.00', 'color': 'a', 'quantity': '5'}, 
 {'product': '25', 'price': '5.00', 'color': 'c', 'quantity': '50'}]

This does not take care of POSTed fields that don't follow the "combination[<digit>].name" convention; you'd have to weed those out yourself (e.g., by wrapping the code above in an exception if the regular expression fails, or by using a simple if statement).
There's also no conversion for numbers to float or integer, since Django has no way of knowing what the input type is, and thus assumes everything is a string.


You may want to rethink your form generation, especially if you want to use Django. Using Django forms (or model forms even) automatically gives you the right output format, and provides proper conversions and type checking.

Have a look at Django's formsets, which is precisely meant for generating multiple forms, and seems to be pretty close to your example form.

(Note: the version 1.9 documentation has, as of current, a red bar above it stating it's an insecure and unsupported version of Django. See if you can upgrade to 2.0.)

Upvotes: 2

Related Questions