May 23, 2008
I've fallen in love with markdown. It's really simple and easy to use -- and results in cleaner, more readable, and compliant HTML than I end up with when I code it by hand.
I also love Django, a fantastic python web development framework. And it even has out-of-the-box support for markdown as a template filter. But I don't use django just to do standard database-driven blogging stuff like this blog -- I also use it to run my whole web site, and use it to organize a lot of projects and pages for which the individual look and feel of the page is an integral part of the content. This means that I can't just plug some "data" about a project into a template -- the template is the product. Consequently, many of my pages are their own one-off templates. But that means there are many cases where the content I want to use markdown with isn't coming from some variable from a database, but is part of a template that I'm writing.
Long story short: I want markdown as a template tag, not just as a filter. So I wrote a very simple template tag to do this:
:::python
# markdown_tag.py: a markdown template tag for django.
from django.contrib.markup.templatetags import markup
from django import template
register = template.Library()
@register.tag(name = "markdown")
def markdown_tag(parser, token):
args = token.contents[len("markdown"):].strip()
nodelist = parser.parse(('endmarkdown',))
parser.delete_first_token()
return MarkdownNode(nodelist, args)
class MarkdownNode(template.Node):
def __init__(self, nodelist, args):
self.nodelist = nodelist
self.args = args
def render(self, context):
output = self.nodelist.render(context)
return markup.markdown(output, self.args)
To use this, save it as "markdown_tag.py", and put it in a "templatetags" directory in your application, like so:
- project/
- application/
- models.py
- views.py
- urls.py
- templatetags/
- markdown_tag.py
Then, in your template, include the following:
{%load markdown_tag %}
...
{% markdown %}
# This is a markdowned heading!
{% endmarkdown %}
This also supports extensions, if you have the latest version of markdown - as in this example, with the codehilite extension:
{% markdown codehilite %}
:::python
print Hello, world!
{% endmarkdown %}