Don't repeat yourself: when you wish to have a block of html with a variable value, but only if the variable is set, you can do this:
{% ifvalue company.contact.email as email %}
<h3>Email address</h3>
<a href='mailto:{{ email }}'>{{ email }}</a>
{% endifvalue %}
Instead of this:
{% if company.contact.email %}
<h3>Email address</h3>
<a href='mailto:{{ company.contact.email }}'>{{ company.contact.email }}</a>
{% endifvalue %}
The tags ifvalue and ifnotvalue are provided by this snippet.
If you don't specify as somename
, then the variable's value will be assigned to the name "value".
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | from django.template import Library
from django.template import FilterExpression, Node, NodeList
from django.template import TemplateSyntaxError, VariableDoesNotExist
register = Library()
def do_ifvalue(parser, token, name, negate=False):
bits = list(token.split_contents())
if len(bits) != 2 and len(bits) != 4:
raise TemplateSyntaxError, "%r takes one or three arguments" % bits[0]
tagname, variable = tuple(bits)[:2]
if len(bits) == 4:
if bits[2] != "as":
raise TemplateSyntaxError, "%r with three arguments must be 'value as name'" % tagname
name = bits[3]
end_tag = 'end' + tagname
nodelist_true = parser.parse(('else', end_tag))
token = parser.next_token()
if token.contents == 'else':
nodelist_false = parser.parse((end_tag,))
parser.delete_first_token()
else:
nodelist_false = NodeList()
expr = FilterExpression(variable, parser)
return IfValueNode(expr, name, nodelist_true, nodelist_false, negate)
@register.tag
def ifvalue(parser, token, name="value"):
"""
Output the contents of the block if the argument is true, assigning
the value of the argument to a context variable ("value" by default).
Examples::
{% ifvalue user.name %}
{{ value }}
...
{% else %}
...
{% endifvalue %}
{% ifvalue user.name as username %}
{{ username }}
...
{% else %}
...
{% endifvalue %}
"""
return do_ifvalue(parser, token, name, False)
@register.tag
def ifnotvalue(parser, token, name="value"):
"""Output the contents of the block if the argument is false. See ifvalue."""
return do_ifvalue(parser, token, name, True)
class IfValueNode(Node):
def __init__(self, var, name, nodelist_true, nodelist_false, negate):
self.var = var
self.name = name
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
self.negate = negate
def __repr__(self):
return "<IfValueNode>"
def render(self, context):
val = self.var.resolve(context, ignore_failures=True)
context[self.name] = val
if (self.negate and not val) or (not self.negate and val):
return self.nodelist_true.render(context)
return self.nodelist_false.render(context)
def get_nodes_by_type(self, nodetype):
nodes = []
if isinstance(self, nodetype):
nodes.append(self)
nodes.extend(self.nodelist_true.get_nodes_by_type(nodetype))
nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype))
return nodes
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
I like it a lot! (but it is unneccessarily python2.4-code and incompatible with python2.3)
you might consider not using decorators, but instead the old python style:
maybe in this case it might even be possible to add your tag to the core? (wishful thinking, of course)
#
@limodou, SmileyChris -- I'd still be using this tag even if I had the expr or with tags; I don't want to have to do:
The assignation of the value to another name is an adjunct to the purpose of entirely omitting the html elements if their contained value is empty.
--
I've just updated the snippet to support filters; in my templatetag naïveté I'd not known how to this initially.
#
Please login first before commenting.