Say I want to have a reusable component, included via {% include %},
which renders a product. So I only have to deal with layout,
formatting, images, etc., once (I'm a big fan of re-use and DRY). The
template fragment will have a lot of {{product.price}},
{{product.picture}}, {{product.nunmInStock}}, etc.
BUT -- not all my templates will have the product I want to render in a
context variable called "product". Some will have it in
"shoppingCartEntry", some in "bestOffer", some maybe even in a {% for
etnries in shoppingcart %}....{% endfor %} -- depending on the context.
But it's always a product.
This would mean I would have to assign different context variables to
my {%include%}'s "product" variable.
Is this supported? Did I miss it in the docs? Or is this not possible
at the moment?
Daniel
This sounds more like a use case for a template tag than for an include.
--
"May the forces of evil become confused on the way to your house."
-- George Carlin
Hi Daniel,
Nope, there's no way to do that. I'd suggest writing a quick custom
template tag for that functionality.
Adrian
--
Adrian Holovaty
holovaty.com | djangoproject.com
>Say I want to have a reusable component, included via {% include %},
>which renders a product. So I only have to deal with layout,
>formatting, images, etc., once (I'm a big fan of re-use and DRY). The
>template fragment will have a lot of {{product.price}},
>{{product.picture}}, {{product.nunmInStock}}, etc.
>
>
This is a work for a template tag and specifically for this case
("include with paramteres") there is a helper inclusion_tag.
In a template tags library (file app_dir/templatetags/app_name.py):
from django import template
register=template.Library()
@register.inclusion_tag('product.html')
def product(arg):
return {'product':arg}
Decorator @register.inclusion_tag takes template name for inclusion (it
should be without ".html" if you don't use latest magic-removal).
Function name will become a name of the tag. It accepts one argument and
returns it in a context dictionary for the included template.
You use it then like this:
{% product bestOffer %}
... and bestOffer will be passed in product.html by the name 'product'.
that *does* look like EXACTLY what I need. Great!
Thanks a lot for your detailed response -- I will try it out as soon as
I'm off work and back to my pet project :-)
Cheers,
Daniel
{% datatofillinthetemplate "templates/macrosnippet.html" %}
Is there a philosophical reason why this doesn't exist?
Cheers,
Tone
Inclusion tag doesn't always just renames context vars. It can (and very
often does) some simple logic which can't be included in a template
syntax. Consider an example of a form field widget that accepts three
optional args and then does some preprocessing kung-fu:
@register.inclusion_tag('artist_widget.html')
def artists(data={}, errors={}, suggest_list=[]):
data=data.copy()
if data.has_key('artists') and type(data['artists'])==str:
data['artists']=[data['artists']]
return {
'data':data,
'errors':errors,
'suggests':suggest_list,
'js_url':settings.JS_URL,
'style_url':settings.STYLE_URL,
}
I bet no template author will want to deal with things like distinction
between a string and a list with this string :-)
And for the simple cases making such a template tag is in my opinion
simple enough. Too many helpers that simplify simplified simple things
are bad :-).
Cheers for the pointer Ivan!
Tone
And
On Fri, Apr 21, 2006 at 10:16:29PM +0800, limodou wrote in re:
Subject: New call tag
> It just like include, but in order to distinguish with
> "include" tag, I call it "call". So you can use it:
>
> {% call "some.html" %} this way just like include tag, and the advanced way:
>
> {% call "some.html" with "a" "b"|capfirst title="title1" %}
> {% call "some.html" with "c" "d" title="title2" %}
>
> So you can see, "call" tag can do like a python function, it can
> receive tuple parameters and key word parameters, just like the
> function:
>
> def func(*args, **kwargs):pass
There's a pattern here... a need for more "programability" in the templates.
I for one believe that templates should NOT have Python (in the case
of Django, or Ruby in the case of Rails) in them -- PERIOD! A very
bad thing to do, security-wise.
The other pattern that emerges here is that there's a need for
being able to at least set variables from within a template.
I propose adding a tag to Django (i.e. not just "write your own
template", but make it, or something like this, a part of Django) for
just that purpose:
{% set variable value %}
where value is parsed so that it can be either a string
or another variable name or of the form a.b.c etc.
in Ivan's case one would just do:
{% set product bestOffer %}
{% include product.html %}
and, in limodou's case one would just do:
{% set title "title1" %}
{% include some.html %}
This would allow one template to pass lists, or objects within
lists or whatever to other included templates. It's not as
"elegant" as passing arguments to templates as what limodou
has done, but it will get that job done; be useful in other
ways; not have Python code in templates; and is fairly simple
and straightforward.
--
Glenn Tenney