Re: Django templates have lexical scope!?

2009-08-26 Thread David De La Harpe Golden

stevedegrace wrote:

> Variables you bind within the template itself don't seem to behave
> this way.
> 
> Instead they are scoped. If a variable is bound inside a block tag,
> the binding is only valid within that block. I didn't do enough
> experiments yet to tell you how it behaves with nested blocks.
> 

I rely on scoping for my templated menus -  I do the following in child
templates to mark a menu item current -

In projects_base.html.djt, say:

{% extends "base.html.djt" %}

{% block menubar0_projects %}
{% with 1 as current %}
{{ block.super }}
{% endwith %}
{% endblock %}

So,it's effectively like the content of the menubar0_projects block in
base.html.djt getting a variable "current" defined. This allows me to
keep all my menu definitions in one template, rather than just
overriding the block wholesale.

I'm a django newbie, maybe there was some other way to do it,
but it works fine.






--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~--~~~~--~~--~--~---



Re: Django templates have lexical scope!?

2009-08-25 Thread James Bennett

On Tue, Aug 25, 2009 at 9:26 PM, stevedegrace wrote:
> I suppose this is easy enough to fix by doing the binding in the view
> when the context is first constructed which would probably have been
> easier in the first place, but now I'm curious and want to know what's
> happening.

If you want something available in the template, then yes, making it
available through the context provided in the view is the way to do
it. The various built-in template tags which can add variables to the
context all have limited scope, and in many cases (e.g., the "with"
tag) this is explicit.

> I never suspected this behaviour and got no inkling to expect it from
> the Django docs. Can anyone with more knowledge of the guts of the
> template rendering system suggest why this happens and if there is any
> way to force variables bound by custom tags into the "global scope"?

The answer is that the template context is not a dictionary. It's a
stack of dictionaries, with fall-through lookup semantics.

Various operations going on in the template push a new dictionary onto
the context stack and populate it, then pop that dictionary off the
context stack when they're done. In general, this is a good thing; for
example, it means it's much easier to have tags do whatever they want
without trampling all over each other's context variables. Many
built-in tags take good advantage of this.

If you truly need a way to make a variable available everywhere in a
template, but it's simply not possible to provide that directly
through the initial context, you want to look at the "dicts" attribute
of the Context instance, which is a list of dictionaries. The last one
in the list (e.g., index -1) is the one that originally came from
instantiating the Context with its initial set of variables, and
during normal template use it will always persist for the life of the
rendering process (someone who wanted to shoot themselves in the foot
could write a tag which manually removes it, but the normal context
push/pop operations will not do this and will raise an exception if
you try to pop the last dictionary out of the stack).


-- 
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~--~~~~--~~--~--~---



Django templates have lexical scope!?

2009-08-25 Thread stevedegrace

I just discovered something I did not expect.

Apparently a Django template does not behave like its context is a
single global scope where if you set a new variable using a custom
template tag it can be accessed anywhere subsequently in the template.

Variables you set into the context initially when you make the method
call to render the template do act like you would expect.

Variables you bind within the template itself don't seem to behave
this way.

Instead they are scoped. If a variable is bound inside a block tag,
the binding is only valid within that block. I didn't do enough
experiments yet to tell you how it behaves with nested blocks.

This can have a distinct effect in child templates, where apparently
nothing you do outside of a block tag "counts", so you can't put a
variable into the global scope simply by binding it before the block
tags. Let's say you use a custom tag to test whether the currently
logged in user has privilege to edit the document, and this sets a
variable into the context which can be checked to decide whether to
display certain controls. (Not intended as a security measure, just
not to clutter the interface with controls the user can't use anyway).
If you include the tag in one block, the variable can only be accessed
in that block!

I suppose this is easy enough to fix by doing the binding in the view
when the context is first constructed which would probably have been
easier in the first place, but now I'm curious and want to know what's
happening.

I never suspected this behaviour and got no inkling to expect it from
the Django docs. Can anyone with more knowledge of the guts of the
template rendering system suggest why this happens and if there is any
way to force variables bound by custom tags into the "global scope"?

Stephen
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~--~~~~--~~--~--~---