Skip to main content

web.py and nested for loops

Lately I've been playing around with <a href="http://www.python.org/">Python</a> and a Python based web framework called <a href="http://webpy.org/">web.py</a>. Today I tried to do something seemingly very simple but ran in a problem I've had before but couldn't find a way around it, unlike last times.

Suppose you have a web.py template that looks a little like this:

$def with (files, ratelists)
       <table>
            <tr><td>Filename</td><td>date_uploaded</td><td>list</td><td>date_imported</td><td></td><td></tr>

        $for file in files:

                <tr><td>$file.filename</td><td>$file.date_uploaded</td><td>$file.list</td><td>file.date_imported</td>

                <td><select name="importinlist">

                $for list in lists:

                        <option value="$list.list_id">$list.name</option>

                </select></td>

        </table>

For some reason the first time the outermost loop was entered, the innermost loop was executed fully, but the second time the outer loop ran, the inner loop resulted in an empty dropdown box. Searching for problems with nested for loops in web.py gave no obvious results. In desperation I started looking through the web.py Google Groups and found a <a href="https://groups.google.com/group/webpy/browse_thread/thread/5bd21de793b146c7#">post hinting at my problem</a>:

> db.select returns webpy's flavored iterator, to get a list from it > > wrap the result in list()

and

> You can even do this: > p = db.select(person).list() > I find it more convenient than wrapping it in list(...).

It appears that db.select() is returning an iterator instead of a list. Once an iterator has reached the end it will obviously not return to the first element so the behaviour described above is exactly as should be expected, but not what I wanted. Adding a .list() call to db.select() and supplying the result to the template above made all my problems go away. I now have dozens of filled dropdowns on my webpage.

So my problem was not with the nested for loops, they were working perfectly. I didn't know results from a web.py database query were an iterator...