I am just trying to write a demostration web page which list a number
of small pictures.
I want it be prgrammable in row and columns.
Suppose i write following line in controller.py
def viewall(self):
pics = [pics for pics in
Pictures.select(orderBy=Pictures.q.shortname)]
return dict(pics=pics, column=4, max_row=4)
I actually find some code that can show each picture in a seperate DIV,
that's look good. But i was not able to "glue" those code into KID
template. So for me, the problem might be: How should I wrote code in
.KID template to represent these pictures' shortname in a table (column
and max_rows), accordingly?
Regards
David
1. Don't use a list comprehension in this case. It's not necessary.
Pictures.select already returns an iterable SQLResults collection; you
can iterate over that in your Kid template and save some time. Just
do:
pics = Pictures.select(orderBy='shortname')
BTW, orderBy takes a string, not a database column.
2. As for the Kid template, your basic idea will be:
<ul py:if="pics">
<li py:for="pic in pics">
<img src="${pic.src}" alt="${pic.alt}" height="${pic.height}"
width="${pic.width}" />
</li>
</ul>
The rest is up to you and your command of HTML and CSS.
Good luck,
David
It takes both, the latter is especially important when you try and sort after
a joined object/table.
Diez
David
def grouper(n, iterable, padvalue=None):
"grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'),
('g','x','x')"
return izip(*[chain(iterable, repeat(padvalue, n-1))]*n)
How should I write .kid template code?
You can try something like this:
<tr py:for="i in range((len(pics)+1)//2)">
<td><img src="${pics[2*i]}" /></td>
<td><img py:if="len(pics)>2*i+1" src="${pics[2*i+1]}" /></td>
</tr>
-- Christoph
Sorry, that was a bit unpythonic. Using the step parameter of range as
suggested by Paul is better:
<tr py:for="i in range(0, len(pics), 2)">
<td><img src="${pics[i]}" /></td>
<td><img py:if="len(pics)>i+1" src="${pics[i+1]}" /></td>
</tr>
Here is a solution for an arbitrary number of cols:
<table py:if="pics">
<tr py:for="i in range(0, len(pics), cols)">
<td py:for="j in range(cols)">
<img py:if="len(pics)>i+j" src="${pics[i+j]}" />
</td>
</tr>
</table>
Well you want to send a list of tuples to your template, where each
tuple has two pictures in it. Then you just iterate through that.
Using the grouper example someone else posted, I would guess something
like this might work:
in controller:
pics = izip(*[chain(Pictures.select(orderBy=Pictures.q.shortname),
repeat('', 1))]*2)
in template:
<tr py:for="pic1, pic2 in pics">
<td>$pic1</td>
<td>$pic2</td>
</tr>
This is entirely untested but should give you an idea.
Ed
I am new to Python and Turbogears, so appreciate your further help.
For simplicity I assumed "pics" is just a list of URLs. If you have a
SQLObject SelectResult, you need to convert it to such a list first,
using something like:
pics = [p.url for p in pics]
Or, if you want to use the SelectResult directly you can determine the
number of pics as pics.count() instead of using len(pics). Then you will
probably have to write something like pics[i].url instead of pics[i].