views:

166

answers:

3

I pass the query with comments to my template:

    COMM = CommentModel.gql("ORDER BY created")

    doRender(self,CP.template,{'CP':CP,'COMM':COMM, 'authorize':authorize()})

And I want to output the number of comments as a result, and I try to do things like that:

    <a href="...">{{ COMM|length }} comments</a>

Thats does not work (yeah, since COMM is GqlQuery, not a list). What can I do with that? Is there a way to convert GqlQuery to list or is there another solution? (first question)[1]

Second question [2] is, how to filter this list in template? Is there a construct like this:

    <a href="...">{{ COMM|where(reference=smth)|length }} comments</a>

so that I can get not only the number of all comments, but only comments with certain db.ReferenceProperty() property, for example.

Last question [3]: is it weird to do such things using templates?

UPD: Questions [1] and [3] are pretty much clear to me, thanks to Nick Johnson and Alex Martelli.

Question [2] is tricky and maybe against the idea of MVC, but I really hope to solve it with templates only :(there are some reasons). It may be as ugly as it gets.

+1  A: 

You could use count on your GqlQuery object, but a GqlQuery doesn't let you add where clauses and the like -- you need Query for that (and its filter method).

Yes, it's very unusual to "pollute" the view logic (i.e., templates) with business logic aspects such as filtering. Normally, the server-side Python code would perform such calls and inject the results in the context, leaving the view logic (template) to deal strictly with presentation issues only -- server side decides what to show, view logic decides only how to show it.

If you prefer a less usual style, with lots of logic in the templates (an architecture that many do consider weird), consider alternative templating systems such as Mako, because the Django templating system is really designed against such "weird architecture";-).

Alex Martelli
+3  A: 

Call .fetch() on the query, returning a list of results, before passing it to the template. Any other solution - such as calling .count() - will result in executing the query multiple times, which wastes CPU and wall-clock time.

Likewise, if you need to filter the query, you should do this in your own code, before passing the results to the template system.

Nick Johnson
A: 

I'm not exactly sure what your trying to accomplish, but you could possibly benefit from URL Mapping, however it will require some extra code. The basic idea is that you would turn whatever value you want to filter against into a "directory". Examples will help:

<a href="basepath/{{ value.tofilterfrom }}">link text</a>

Then in your python code you would need modify your WSGIApplication object with a unique handler. Something like:

application = WSGIApplication(
                              [('/', MainPage),
                               (r'/basepath/(.*)', Products),

Just create a new class called Products, and it will automatically pick up the filter value and store it in a variable for you, like so:

class Products(webapp.RequestHandler):
    def get(self, ProductID):

And thats it, you can expand this as much as you want, add more levels. In the class Products you would just filter your Query object using the ProductID variable as your criteria.

I have a more in depth write up at my Blog if you want to read more on this.

Timbermar