views:

359

answers:

4

Say I have a template

<html>
<div>Hello {{name}}!</div>
</html>

While testing it, it would be useful to define the value of the variable without touching the python code that invokes this template. So I'm looking for something like this

{% set name="World" %}     
<html>
<div>Hello {{name}}!</div>
</html>

Does something like this exists in Django?

Thanks

+5  A: 

You probably want the with template tag.

{% with "World" as name %}     
<html>
<div>Hello {{name}}!</div>
</html>
{% endwith %}
John
+3  A: 

There are tricks like the one described by John; however, Django's template language by design does not support setting a variable (see the "Philosophy" box in Django documentation for templates).
Because of this, the recommended way to change any variable that is by touching the python code.

Roberto Liffredo
Thanks for the pointer. From a perspective of a designer is it sometimes easier to quickly set a variable to test various states of a page while designing it. Not suggesting this practice to be used in a running code.
Alexis
the "with" tag is accepted in django1.0. So looks like they are finally amending their philosophy :).
Evgeny
As a matter of facts, the "with" tag is just for aliases. This may have a huge impact on performance (and on readability as well!) but it is not really setting a variable in traditional programming terms.
Roberto Liffredo
A: 

Get rid of the Django variable completely and put in text:

<html>
<div>Hello John!</div>
</html>

What is the point of replacing variable with another that you are going to make up yourself?

Designers don't need to know/use any variables. Later the coder can go in and put the variables as needed.

drozzy
A: 

An alternative way that doesn't require that you put everything in the "with" block is to create a custom tag that adds a new variable to the context. As in:

class SetVarNode(template.Node):
    def __init__(self, new_val, var_name):
        self.new_val = new_val
        self.var_name = var_name
    def render(self, context):
        context[self.var_name] = self.new_val
        return ''

@register.tag
def setvar(parser,token):
    # This version uses a regular expression to parse tag contents.
    try:
        # Splitting by None == splitting by spaces.
        tag_name, arg = token.contents.split(None, 1)
    except ValueError:
        raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents.split()[0]
    m = re.search(r'(.*?) as (\w+)', arg)
    if not m:
        raise template.TemplateSyntaxError, "%r tag had invalid arguments" % tag_name
    new_val, var_name = m.groups()
    if not (new_val[0] == new_val[-1] and new_val[0] in ('"', "'")):
        raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
    return SetVarNode(new_val[1:-1], var_name)

This will allow you to write something like this in your template:

{% setvar "a string" as new_template_var %}

Note that most of this was taken from here

Karim