views:

1502

answers:

2

I need to perform a filtered query from within a django template, to get a set of objects equivalent to python code within a view:

queryset = Modelclass.objects.filter(somekey=foo)

In my template I would like to do

{% for object in data.somekey_set.FILTER %}

but I just can't seem to find out how to write FILTER.

+18  A: 

You can't do this, which is by design. The Django framework authors intended a strict separation of presentation code from data logic. Filtering models is data logic, and outputting HTML is presentation logic.

So you have several options. The easiest is to do the filtering, then pass the result to render_to_response. Or you could write a method in your model so that you can say {% for object in data.filtered_set %}. Finally, you could write your own template tag, although in this specific case I would advise against that.

Eli Courtwright
Thanks for the clarification of django design concept.I am using the model method approach.
Ber
+3  A: 

I run into this problem on a regular basis and often use the "add a method" solution. However, there are definitely cases where "add a method" or "compute it in the view" don't work (or don't work well). E.g. when you are caching template fragments and need some non-trivial DB computation to produce it. You don't want to do the DB work unless you need to, but you won't know if you need to until you are deep in the template logic.

Some other possible solutions:

  1. Use the {% expr <expression> as <var_name> %} template tag found at http://www.djangosnippets.org/snippets/9/ The expression is any legal Python expression with your template's Context as your local scope.

  2. Change your template processor. Jinja2 (http://jinja.pocoo.org/2/) has syntax that is almost identical to the Django template language, but with full Python power available. It's also faster. You can do this wholesale, or you might limit its use to templates that you are working on, but use Django's "safer" templates for designer-maintained pages.

Peter Rowell