Using Markdown with Django 1.7

Friday, May 9th, 2014

Markdown is great. As a formatting language, I find it to be pretty much unparalleled for speed and ease of syntax. Not having to think overly hard about style allows you to focus purely on the quality of the content.

At work, we use GitHub extensively, which means that Markdown is a standard. Issues, pull requests and comments all accept the syntax, so it feels very familiar. Given a choice, I now prefer to do all of my writing in Markdown. Using Draft makes this very convenient - I can write in Markdown and output my writing to HTML. However, this has always felt like a bit of an extra step to me. What I really wanted to be able to do was just dump my Markdown into my blog and have it render as HTML.

One way to do this would be to use a static site generator like Pelican or Jekyll. However, my site is a Django app, and I want to keep it that way. Unfortunately, Django deprecated their built-in support for Markdown rendering in 1.5. Fortunately, there is an easy way around this!

Using Markdown with Django 1.5+

The Python markdown package is the secret to adding Markdown support back into our Django templates. In order to make it as easy as possible to render Markdown, we want to create a custom template filter. It will look a little something like this:

In order to render content written in Markdown on a page, we can just add the filter to the relevant context variable. Don't forget to load the file containing the template tag!

Et voila - now we can write our content as Markdown, throw it into a text field on a Django form, and see it rendered as HTML on our display page. Easy! So easy, in fact, that this post itself was written in Markdown and put straight into my blog.

Note: For the security-minded, it's also possible to change the escape behaviour of the markdown function to disallow raw HTML from being passed through. This way, we can expose a Markdown form to our users without worrying that they will inject malicious code into our pages! In the example above, I've used safe_mode = 'escape' which automatically escapes raw HTML to a safe equivalent.

comments powered by Disqus