DRY up your Django templates with Showell Markup

3 views
Skip to first unread message

Steve Howell

unread,
Nov 27, 2009, 1:08:17 PM11/27/09
to Django users
I would like to announce an early version of Showell Markup. It
allows you or your designer to create web pages without the visual
clutter of </table>, </ol>, {% endfor %}, {% endwith %}, and friends.

Unlike templating solutions that compete with Django, the Showell
Markup plays nice with Django and still delegates all the heavy
lifting to Django, so you still get variable interpolation, extends,
custom filter tags, include, etc. from Django.

Showell Markup just does two jobs and does them well:

1. Allow for indentation-based blocking (both for HTML and Django
tags)
2. Allow for clean HTML one-liners that truly separate markup from
content.

The implementation of Showell Markup is just a preprocessor to publish
Django templates. You edit the Showell Markup from a master file and
then publish the templates to their locations within the Django
directory structure and you're done. You can keep both markups under
source control. The preprocessor writes clean markup, so you can
debug at the Django level as needed. Also, you are not forced to use
Showell idioms everywhere; normal Django and HTML still passes through
the preprocessor without modification.

You can find the implementation here:

http://www.djangosnippets.org/snippets/1819/

The indentation feature is, of course, inspired by Python/YAML/HAML/
etc.

The one-liner syntax is inspired by Django's use of pipes to implement
filters.

Here are some examples (some of which look better in a monospace
font)...

You can use indentation syntax for HTML tags like table.


Instead of this...

<table>
<tr>
<td>
Right
</td>
<td>
Center
</td>
<td>
Left
</td>
</tr>
</table>

You can write DRY code this...

>> table
>> tr
>> td
Right
>> td
Center
>> td
Left


Lists work the same way, and note that attributes are not a
problem.


Instead of this...

<div class="spinnable">
<ul>
<li id="item1">
One
</li>
<li id="item2">
Two
</li>
</ul>
</div>

You can write DRY code this...

>> div class="spinnable"
>> ul
>> li id="item1"
One
>> li id="item2"
Two


This tool should play nice with most templating engines, but it
has
specific support for Django.


Instead of this...

{% extends 'base.html' %}
{% load smartif %}

{% block body %}
{% for book in books %}
{{ book }}
{% endfor %}

{% if condition %}
Display this
{% elif condition %}
Display that
{% else %}
{% include 'other.html' %}
{% endif %}
{% endblock %}

You can write DRY code this...

%% extends 'base.html'
%% load smartif

%% block body
%% for book in books
{{ book }}

%% if condition
Display this
%% elif condition
Display that
%% else
%% include 'other.html'


The tool also lets you dry up individual lines of HTML using a
piping concept. Note the clean separation between markup and
content.

Instead of this...

<tr class="header_row">
<th class="first_column">Original Author</th>
<th>Commenters</th>
<th>Title</th>
<th>Action</th>
<th>Last words</th>
<th>By</th>
<th>When</th>
</tr>

<ol class="boring_list">
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>{{ element4|join:',' }}</li>
</ol>

You can write DRY code this...

>> tr class="header_row"
Original Author | th class="first_column"
Commenters | th
Title | th
Action | th
Last words | th
By | th
When | th

>> ol class="boring_list"
One | li
Two | li
Three | li
{{ element4|join:',' }} | li


Pipes get applied from right to left, as you would expect.
You can also throw a br on at the end.


Instead of this...

<span class="greeting"><b>Hello World!</b></span><br />
<span class="parting_words"><i>Goodbye World!</i></span><br />
<hr />
<p class="praise">
Indentation-based syntax is so
Pythonic!
</p>

You can write DRY code this...

Hello World! | b | span class="greeting" ; br
Goodbye World! | i | span class="parting_words"; br
; hr
>> p class="praise"
Indentation-based syntax is so
Pythonic!


There are three special shortcuts for LINK, FORM, and HIDDEN.
You could easily extend the preprocessor to do more.


Instead of this...

<a href="{% url collection.archive referral.pk %}">Archive</a>
<a href="{% url home.home %}">Home</a>
<a href="{% url friendship.friends %}">Friends</a>
<a href="{% url referrals.create %}">Create a card</a>
<a href="{% url activity.recent_changes %}">Recent changes</a>

<form action="{% url referrals.create %}" method="POST">
{{ form.as_p }}
<input type="hidden" name="referral"
value="{{ referral.id }}" />
</form>

You can write DRY code this...

Archive LINK collection.archive referral.pk
Home LINK home.home
Friends LINK friendship.friends
Create a card LINK referrals.create
Recent changes LINK activity.recent_changes

>> FORM referrals.create
{{ form.as_p }}
{{ referral.id } | HIDDEN referral

I am calling the markup Showell Markup for now, but a better name
might be in order. "Showell" rhymes with "towel." It is my username,
and hopefully it "shows well" too.

David Martorana

unread,
Dec 4, 2009, 2:37:58 PM12/4/09
to Django users
I don't want to jump on something too quickly, being somewhat
unproven, but it's a nice thing to have with GHRML being dead and HAML
being Ruby only. I'll keep an eye on this!

What plans do you have for future improvement?

Dave

On Nov 27, 1:08 pm, Steve Howell <showel...@yahoo.com> wrote:
> I would like to announce an early version ofShowellMarkup.  It
> allows you or your designer to create web pages without the visual
> clutter of </table>, </ol>, {% endfor %}, {% endwith %}, and friends.
>
> Unlike templating solutions that compete with Django, theShowell
> Markup plays nice with Django and still delegates all the heavy
> lifting to Django, so you still get variable interpolation, extends,
> custom filter tags, include, etc. from Django.
>
> ShowellMarkup just does two jobs and does them well:
>
>   1. Allow for indentation-based blocking (both for HTML and Django
> tags)
>   2. Allow for clean HTML one-liners that truly separate markup from
> content.
>
> The implementation ofShowellMarkup is just a preprocessor to publish
> Django templates.  You edit theShowellMarkup from a master file and
> then publish the templates to their locations within the Django
> directory structure and you're done.   You can keep both markups under
> source control.  The preprocessor writes clean markup, so you can
> debug at the Django level as needed.  Also, you are not forced to useShowellidioms everywhere; normal Django and HTML still passes through
> I am calling the markupShowellMarkup for now, but a better name

David Martorana

unread,
Dec 5, 2009, 2:45:09 PM12/5/09
to Django users
I wrote this rather quickly. It allows you to put a template.showell
file in each app folder, and will render the templates on demand if
you call "render_showell_to_response(...)". It'll check the last
modification time of the .showell files, and re-renders them if
they've changed, allowing you to come close to ignoring any running of
the Showell pre-processor on your own.

===

import os, sys
import showell

from django.conf import settings
from django.utils.importlib import import_module
from django.shortcuts import render_to_response

from datetime import datetime

_SHOWELL_FILES_ = []

def render_showell_to_response(template, *args, **kwargs):
'''
Monitor any templates.showell file in an app folder
for changes, and republish them if necessary before
serving up the request
'''
# Get a list of app showell files
# Runs only once
if len(_SHOWELL_FILES_) == 0:
for app in settings.INSTALLED_APPS:
m = import_module(app)
for path in m.__path__:
sfile = os.path.join(path, 'templates.showell')
if os.path.exists(sfile):
_SHOWELL_FILES_.append(sfile)

# Check the date of each showell file
for sfile in _SHOWELL_FILES_:
if not hasattr(settings, '_SHOWELL_LAST_RENDERED_') or \
datetime.fromtimestamp(os.path.getmtime(sfile)) >
settings._SHOWELL_LAST_RENDERED_:
#print 'Republishing %s' % sfile
showell.publish(sfile)

# Set the last time we looked
settings._SHOWELL_LAST_RENDERED_ = datetime.now()

# Render normal template
return render_to_response(template, *args, **kwargs)

On Nov 27, 1:08 pm, Steve Howell <showel...@yahoo.com> wrote:
> I would like to announce an early version ofShowellMarkup.  It
> allows you or your designer to create web pages without the visual
> clutter of </table>, </ol>, {% endfor %}, {% endwith %}, and friends.
>
> Unlike templating solutions that compete with Django, theShowell
> Markup plays nice with Django and still delegates all the heavy
> lifting to Django, so you still get variable interpolation, extends,
> custom filter tags, include, etc. from Django.
>
> ShowellMarkup just does two jobs and does them well:
>
>   1. Allow for indentation-based blocking (both for HTML and Django
> tags)
>   2. Allow for clean HTML one-liners that truly separate markup from
> content.
>
> The implementation ofShowellMarkup is just a preprocessor to publish
> Django templates.  You edit theShowellMarkup from a master file and
> then publish the templates to their locations within the Django
> directory structure and you're done.   You can keep both markups under
> source control.  The preprocessor writes clean markup, so you can
> debug at the Django level as needed.  Also, you are not forced to useShowellidioms everywhere; normal Django and HTML still passes through
> I am calling the markupShowellMarkup for now, but a better name
Reply all
Reply to author
Forward
0 new messages