zmdc
zmdc

Reputation: 117

get nth item from for loop in a form - python/google app engine/jinja2

I have a list of members, from a for loop in jinja2 with select and option

I would like to be able to select one of the members from the for loop, and add that member to another list of entries to an event, with the extra options available to the user. (getting the member is easy, from the value of the button, getting the options is the problem)

For example:

Jinja2 Template:

<form method="post" action="add_member_to_list">
  <table>
  {% for member in members %}
    <tr>
      <th>{{ member.name }}</th>
      <td><input type="checkbox" name="in_out"></td>
      <td><select name="day">
            <option>Monday</option>
            <option>Wednesday</option>
          </select>
      </td>
      <td><button type="submit" name="id" value="{{ member.id }}">Add</button></td>
    </tr>
  {% endfor %}
  </table>
</form>

in Google App Engine - Python

class AddUser(BaseHandler):
    def post(self):
        in_out = self.request.get("in_out")
        id = self.request.get("id")
        day = self.request.get("day")

In this scenario, self.response.get("day") only ever returns the option selected for the first iteration of the for loop.

The checkbox; self.request.get("in_out"), returns on or off as expected.

So submitting the nth iteration of the for loop: "Monday" is always returned from select/option.

How can I get the select/option corresponding to the nth iteration of the for loop?

Thanks!

Upvotes: 0

Views: 403

Answers (3)

gipsy
gipsy

Reputation: 3859

The simplest solution will be to move the form tag into your for loop

  <table>
  {% for member in members %}
<form method="post" action="add_member_to_list">
    <tr>
      <th>{{ member.name }}</th>
      <td><input type="checkbox" name="in_out"></td>
      <td><select name="day">
            <option>Monday</option>
            <option>Wednesday</option>
          </select>
      </td>
      <td><button type="submit" name="id" value="{{ member.id }}">Add</button></td>
    </tr>
</form>
  {% endfor %}
  </table>

Upvotes: 1

zmdc
zmdc

Reputation: 117

I found a quite simple solution for this:

instead of

day = self.request.get("day")

I used

day = self.request.get_all("day")

Which returns a list of all the options from the select, including the option the user choose for the member.

Then, for the Add Button, instead of

<td><button type="submit" name="id" value="{{ member.id }}">Add</button></td>

I assigned the name "loop" and a value of {{ loop.index0}}

so,

self.request.get("loop")

returns the position of the member selected, corresponding the position on the day list of the target. voila.

The member I get from a hidden td instead of from the submit button.

The final code:

<form method="post" action="add_member_to_list">
  <table>
    {% for member in members %}
     <tr>
       <th>{{ member.name }}</th>
       <td><input type="checkbox" name="in_out"></td>
       <td>
         <select name="day">
          <option>Monday</option>
          <option>Wednesday</option>
         </select>
       </td>
       <td class="hidden"><input name="id" value="{{ member.id }}"></td>
       <td><button type="submit" name="loop" value="{{ loop.index0 }}">Add</button></td>
    </tr>
  {% endfor %}
 </table>
</form>

class AddUser(BaseHandler):
    def post(self):
        day = self.request.get_all("day")
        id = self.request.get_all("id")
        loop = self.request.get("loop")
        target_day = day[int(loop)]
        target_id = id[int(loop)]

Niiice.

Upvotes: 0

Aerodyno
Aerodyno

Reputation: 469

So your resulting form has multiple fields with the same name, right?

Like for the first member, there is a and for the second member, there is also a ?

If so, forms don't support that. You have to have a unique name for each field. You'll have to throw in a memberID on each iteration of the loop, or come up with a better design. Something like <select name="day{{member.id}}"> would be a hacky fix.

Another way is you just leave the in_out and day OUT of the for loop, keep it outside.

I hope that helps.

Upvotes: 0

Related Questions