Declare a variable in a template

4,809 views
Skip to first unread message

skullvulture

unread,
Aug 3, 2006, 4:05:40 PM8/3/06
to Django users
Is there anyway to declare variables within a template? I'm coming
from a Zope background where with dtml you have the dtml-let tag and
with ZPT you have tal:define. Django's templating seems so much cooler
than Zope's, but I'm missing a declare or define tag.

The idea I want to be able to do is:

{% declare nopastshows=0 %}
{% for show in object_list %}
{% if show.is_past_show %}
<h4>{{ show.show_date.month }}/{{ show.show_date.day }} {{
show.show_title}} @ <a href="{{ show.location_url }}" target="new">{{
show.location_name }}</a></h4>
{% else %}
{% nopastshows=1 %}
{% endif %}
{% endfor %}

{% if nopastshows %}
<h4>No past show information available</h4>
{% endif %}


I saw the topic on writing a custom tag for the food selection, but
that seems like a lot of work for such a simple task. Does anyone have
any suggestions? Thanks.

James Bennett

unread,
Aug 3, 2006, 4:32:29 PM8/3/06
to django...@googlegroups.com
On 8/3/06, skullvulture <sbog...@gmail.com> wrote:
> Is there anyway to declare variables within a template? I'm coming
> from a Zope background where with dtml you have the dtml-let tag and
> with ZPT you have tal:define. Django's templating seems so much cooler
> than Zope's, but I'm missing a declare or define tag.

There is no way to declare a new variable using only the template
language's constructs, and I'd say that's pretty much a deliberate
choice; the template system isn't meant to be a programming language,
and the place to set variables is in the view.

--
"May the forces of evil become confused on the way to your house."
-- George Carlin

Adrian Holovaty

unread,
Aug 3, 2006, 4:36:10 PM8/3/06
to django...@googlegroups.com
On 8/3/06, skullvulture <sbog...@gmail.com> wrote:
> Is there anyway to declare variables within a template? I'm coming
> from a Zope background where with dtml you have the dtml-let tag and
> with ZPT you have tal:define. Django's templating seems so much cooler
> than Zope's, but I'm missing a declare or define tag.
>
> The idea I want to be able to do is:
>
> {% declare nopastshows=0 %}
> {% for show in object_list %}
> {% if show.is_past_show %}
> <h4>{{ show.show_date.month }}/{{ show.show_date.day }} {{
> show.show_title}} @ <a href="{{ show.location_url }}" target="new">{{
> show.location_name }}</a></h4>
> {% else %}
> {% nopastshows=1 %}
> {% endif %}
> {% endfor %}
>
> {% if nopastshows %}
> <h4>No past show information available</h4>
> {% endif %}

Nope, there's no way to declare variables within templates, and that's
on purpose. (See
http://www.djangoproject.com/documentation/design_philosophies/ for
the rundown.)

There are a couple of ways to solve your particular problem:

* Calculate the nopastshows variable within your view, where the
"business logic" belongs. If you're using a generic view, you won't be
able to do this.

* If you're not using any of the objects with is_past_show == False,
then change your view so that object_list is only the objects with
is_past_show==True. Then you can do this:

{% if object_list %}
(Iterate and display objects.)
{% else %}
No past show information available.
{% endif %}

* You can write a custom template tag, as you noted.

Hope this helps,
Adrian

--
Adrian Holovaty
holovaty.com | djangoproject.com

Don Arbow

unread,
Aug 3, 2006, 5:14:38 PM8/3/06
to django...@googlegroups.com
On Aug 3, 2006, at 1:05 PM, skullvulture wrote:
>
> Is there anyway to declare variables within a template? I'm coming
> from a Zope background where with dtml you have the dtml-let tag and
> with ZPT you have tal:define. Django's templating seems so much
> cooler
> than Zope's, but I'm missing a declare or define tag.
>
> ...

>
> I saw the topic on writing a custom tag for the food selection, but
> that seems like a lot of work for such a simple task. Does anyone
> have
> any suggestions? Thanks.


Since you are only displaying past_shows in your list, I would simply
query for those in your view. Then you can test to see if the
object_list is empty and display the appropriate message.

{% if object_list %}


{% for show in object_list %}

...
{% endfor %}
{% else %}


<h4>No past show information available</h4>
{% endif %}

Don

skullvulture

unread,
Aug 3, 2006, 5:45:39 PM8/3/06
to Django users
Don,

I have another loop above that displays upcoming shows. Is it possible
to have two object lists, one of upcoming and one of past shows be
passed to the template?

Thanks


Adrian,

I understand your philosophy of separating presentation and logic, but
even in your there you say that the templates contain "presentation and
presentation-related logic." Declaring a variable for this case seems
like pretty standard presenation-related logic.

Thanks

James Bennett

unread,
Aug 3, 2006, 5:46:04 PM8/3/06
to django...@googlegroups.com
On 8/3/06, Adrian Holovaty <holo...@gmail.com> wrote:
> * If you're not using any of the objects with is_past_show == False,
> then change your view so that object_list is only the objects with
> is_past_show==True. Then you can do this:

Assuming the use of the object_list generic view, this is pretty easy;
it's just tacking a filter() onto the view's 'queryset' argument and
setting 'allow_empty' (so that it won't throw a 404 when there are no
matching shows).

Don Arbow

unread,
Aug 3, 2006, 7:21:35 PM8/3/06
to django...@googlegroups.com
On Aug 3, 2006, at 2:45 PM, skullvulture wrote:
> I have another loop above that displays upcoming shows. Is it
> possible
> to have two object lists, one of upcoming and one of past shows be
> passed to the template?


Yes, you can pass any sort of data that you want to your template.
So, if you have two lists, upcoming_shows and past_shows, you can
pass them from your view. In the example below, list_1 and list_2 are
the query sets you generate in your view. I guessed at the query you
would use to generate, but you should get the idea. The key values in
the returned dictionary should match those in your template.

list_1 = Shows.objects.filter(upcoming=True)
list_2 = Shows.objects.filter(past=True)

return render_to_response('template.html'
{'upcoming_shows':list_1, 'past_shows':list_2})

Don


James Bennett

unread,
Aug 3, 2006, 8:01:40 PM8/3/06
to django...@googlegroups.com
On 8/3/06, skullvulture <sbog...@gmail.com> wrote:
> I have another loop above that displays upcoming shows. Is it possible
> to have two object lists, one of upcoming and one of past shows be
> passed to the template?

A view can pass any number of variables it wants to, with any legal
Python values it wants to, so yeah.

> I understand your philosophy of separating presentation and logic, but
> even in your there you say that the templates contain "presentation and
> presentation-related logic." Declaring a variable for this case seems
> like pretty standard presenation-related logic.

Not really; templates decide _how_ to present, views decide _what_ to
present. Whether there are objects with a particular attribute or
value is something that belongs in the "what to present" part of
things.

limodou

unread,
Aug 3, 2006, 8:20:54 PM8/3/06
to django...@googlegroups.com
I'v written a Custom Tag named "expr", you can try it.

http://code.djangoproject.com/wiki/ExprTag


--
I like python!
My Blog: http://www.donews.net/limodou
My Django Site: http://www.djangocn.org
NewEdit Maillist: http://groups.google.com/group/NewEdit

JHeasly

unread,
Aug 4, 2006, 3:16:41 AM8/4/06
to Django users
Don Arbow wrote:
>
> list_1 = Shows.objects.filter(upcoming=True)
> list_2 = Shows.objects.filter(past=True)
>
> return render_to_response('template.html'
> {'upcoming_shows':list_1, 'past_shows':list_2})
>
> Don

Don,

Thanks for the clean, clear example! It helped me see a way out in a
variation of the same situation, i.e., a
loader.get_template('template.html').render(Context({'upcoming_shows':list_1,
'past_shows':list_2})) situation. I'm using the Django templates & API
in a "outside-of-Django" Python script to create and send an e-mail
document.

{%minor_nit%}In your render_to_response example, oughtn't there be a
comma after 'template.html'?{% end minor_nit %}

Thanks again!

John

Reply all
Reply to author
Forward
0 new messages