Passing a list as query parameter and storing the retrieved rows in a list

88 views
Skip to first unread message

Meinolf

unread,
Sep 19, 2016, 1:59:27 PM9/19/16
to web2py-users
Hi There,

When i test the code below, for a list that is supposed to have multiple items, i only get one result for the last item, did i miss something in the for loop or anywhere else?

for i in range(0, (len(getcourseids)-1)):
            c = db.item.id==getcourseids[i].item_id
            s.append(db(c).select(db.item.course_title)[i])

Any help will be appreciated.

villas

unread,
Sep 20, 2016, 5:18:10 PM9/20/16
to web2py-users
Maybe you could better use more of the power of web2py.  Something like this....?

s = db( db.item.id.belongs(getcourseids.values()) ).select(
db.item.
course_title).as_list()

or perhaps a bit longer, something like this...

rows
= db( db.item.id.belongs(getcourseids.values()) ).select(
db.item.
course_title)
s = [r.course_title for r in rows]

Meinolf

unread,
Sep 21, 2016, 3:03:41 AM9/21/16
to web2py-users
I tried both approaches but i get the following error:

<type 'exceptions.AttributeError'> 'Rows' object has no attribute 'values'


the Rows object being referred to in the error is getcourseids, which is true because it holds a set of rows retrieved from the database before. How can i get around it then?

Meinolf

unread,
Sep 21, 2016, 3:30:49 AM9/21/16
to web2py-users
OMG, Is this normal?????
i got chills telling me it had something to do with the For Loop, played around with the LBs and UBs and the following worked:

        for i in range(-1, (len(getcourseids)-1)):
            c = db.item.id==getcourseids[i].item_id
            s.append(db(c).select(db.item.course_title)[i])

Now i'm puzzled as to why give a lower bound of -1 for the range, will this keep on working or my code could later crash???? I put it under a Try..Except  block though..please help if there's a safer alternative, this is new to me and sort of contradicts what i know of starting from 0.

Dave S

unread,
Sep 21, 2016, 2:46:24 PM9/21/16
to web2py-users
On Wednesday, September 21, 2016 at 12:30:49 AM UTC-7, Meinolf wrote:
OMG, Is this normal?????
i got chills telling me it had something to do with the For Loop, played around with the LBs and UBs and the following worked:

        for i in range(-1, (len(getcourseids)-1)):
            c = db.item.id==getcourseids[i].item_id
            s.append(db(c).select(db.item.course_title)[i])

Now i'm puzzled as to why give a lower bound of -1 for the range, will this keep on working or my code could later crash???? I put it under a Try..Except  block though..please help if there's a safer alternative, this is new to me and sort of contradicts what i know of starting from 0.


The normal Python way of writing a loop on a list is:
     for id in getcourseid:
       c
= db.item.id == id.item_id
       s
.append(db(c).select(db.item.course_title))
Giving an explicit range would be appropriate if you were processing only a portion of the list, but there you could use Python slices to do that:
     for id in getcourseid[3:7]:
       etc

As for your effort to use villas' suggestion, you should have replace his "values" with your "item_id".

You might want to scan Chapter 3 for some examples of Python coding and web2py queries.
<URL:http://web2py.com/books/default/chapter/29/03/overview#An-image-blog>
and just below that, the wiki example, especially def show: and the pagecomments query.

/dps
 

Anthony

unread,
Sep 21, 2016, 2:59:05 PM9/21/16
to web...@googlegroups.com
On Wednesday, September 21, 2016 at 3:30:49 AM UTC-4, Meinolf wrote:
OMG, Is this normal?????
i got chills telling me it had something to do with the For Loop, played around with the LBs and UBs and the following worked:

        for i in range(-1, (len(getcourseids)-1)):

First, if you want the subscripts of a list, just do range(len(thelist)). Do not subtract 1 from the length of the list -- range already handles that for you (it returns integers that are strictly less than the second argument). Also, no need to start with 0, as that is the default. And don't start with -1 -- when used as a subscript, that will simply retrieve the last item in the list, not the first. Also, in Python 2, use xrange() in for loops, which is more memory efficient (in Python 3, range has been replaced by xrange).
 
            c = db.item.id==getcourseids[i].item_id
            s.append(db(c).select(db.item.course_title)[i])

Here it is not clear why you are subscripting the result of the select with [i]. Presumably each query returns a single matching row, which means you want the subscript to always be [0] -- otherwise, you will get a list index out of range error.

Actually, given that you don't really need the index of each element in the list, you can instead just iterate over the list itself:

for item in getcourseids:

And if you did need the index values in addition to the elements, the more typical approach in Python would be:

for i, item in enumerate(getcourseids):

Anyway, in this case you should not be using the above method at all, as it is very inefficient (you are doing a separate database query for every single item in getcourseids, when you could instead use a single query). Villas has the right idea, but getcourseids.values() assumes getcourseids is a dictionary -- presumably it is actually a Rows object. So, you can do:

s = db(db.item.id.belongs([c.item_id for c in getcourseids])).select(db.item.course_title)

Note, the above is a Rows object. You can convert it to a list if you really need a list, but most likely you can work with the Rows object (it can be iterated and indexed just like a list).

Assuming getcourseids is a Rows object and the only reason it was created was to get the item_id values to be used in this subsequent query, you can instead skip the creation of getcourseids and just use a nested select:

id_query = db([your query to retrieve course ids])._select(db.your_course_table.item_id)
s
= db(db.item.id.belongs(id_query)).select(db.item.course_title)

Anthony

Meinolf

unread,
Sep 28, 2016, 2:54:23 AM9/28/16
to web2py-users
Thanks Anthony, i understand clearly now, getcourseids was indeed a Rows object and it works now with just  this line:
s = db(db.item.id.belongs([c.item_id for c in getcourseids])).select(db.item.course_title)

Thanks a lot really!
Reply all
Reply to author
Forward
0 new messages