I have a need to have multiple sections of name/value pairs with a header on some pages. Something like:
<div class="row">
<div class="span6">
<div class="row"><div class="span3"><h2>History:</h2></div></div>
<div class="row"><div class="span2">Date added to fleet:</div><div class="span2">{{plane.dateAddedToFleet}}</div></div>
<div class="row"><div class="span2">Total Flight Time:</div><div class="span2">{{plane.totalFlightTime|asTime}}</div></div>
<div class="row"><div class="span2">Total Number of Flights:</div><div class="span2">{{plane.totalNumberOfFlights}}</div></div>
</div>
</div>
So that’s wrong. I first tried creating a custom tag to render the entire section that would be used like this within the django template:
{% specgroup "History" "Date added to fleet" plane.dateAddedToFleet "Total Flight Time:" plane.totalFlightTime|asTime "Total Number of Flights" plane.totalNumberOfFlights %}
The custom tag code for the above is:
# tags for groups of fields (such as on plane detail page)
@register.simple_tag
def specgroup(*args):
"""group header label1 value1 label2 value2 ...."""
header= args[0]
logging.getLogger().error(header)
html = """
<div class="row">
<div class="span6">
<div class="row"><div class="span3"><h2>%s:</h2></div></div>
"""%header
# parse remainder of args as label1 value1 label2 value2 etc....
data = args[1:]
diter = iter(data)
for d in diter:
data = {}
data["label"] = d
data["value"] = diter.next()
html += """ <div class="row"><div class="span2">%(label)s:</div><div class="span2">%(value)s</div></div>"""%data
html += """
</div>
</div>"""
return html
You cannot split the arguments across multiple lines to clean up the mess that is the call to the custom tag. So back to the drawing board.
I compromised with this:
{% specheader "History" %}
{% specdata "Date added to fleet" plane.dateAddedToFleet %}
{% specdata "Total Flight Time" plane.totalFlightTime|asTime %}
{% specdata "Total Number of Flights" plane.totalNumberOfFlights %}
{% specend %}
It’s my favorite compromise between brevity and maintainability.
The custom tags to implement this are:
@register.simple_tag
def specheader(header):
return """
<div class="row">
<div class="span6">
<div class="row"><div class="span3"><h2>%s:</h2></div></div>"""%header
@register.simple_tag
def specdata(label,value):
return '<div class="row"><div class="span2">%s:</div><div class="span2">%s</div></div>'%(label, value)
@register.simple_tag
def specend():
return "</div></div>"
Which is also cleaner than the all-in-one tag.
It’s not for me, but Skylar Savland on github created a Django Template macros with args and kwargs gist that is another solution to this problem.
I’d love to hear ideas that solve this problem in a better way.