I'm a web developer in Norfolk. This is my blog...

Django Blog Tutorial - the Next Generation - Part 6

Welcome back! In this tutorial we’ll cover the following:

Fixing bugs the TDD way

Setting up syntax highlighting for code snippets

Tidying up the front end

Apologies, but I’m holding over implementing the search and additional feeds for a future instalment - in the past I’ve tried to cover too much in one post and that has led to me putting them off for much too long. So this instalment and future ones are going to be shorter so I can get them out the door quicker.

Ready? Let’s get started!

Fixing bugs

When someone reports a bug, it’s tempting to just dive straight in and start fixing it. But TDD cautions us against this practice. If we have a bug, then our tests should have caught it. If they don’t, then before we fix the bug, we have to make sure we can catch it if it crops up in future by implementing a test for it, and ensuring that it fails. Once that test is in place, we can then go ahead and fix the bug, safe in the knowledge that if it should reappear in future, we will be warned when our tests run.

As it happens, we have a bug in our web app. If you activate your virtualenv in the usual way and run the development server, and then try to create a new post without adding a tag, you’ll see that it fails as the tag is empty. Now, it’s pretty obvious that this is because the tags attribute of the Post model cannot be blank, so we have a good idea of what we need to do to fix this. But to make sure it never occurs again, we need to implement a test first.

If you compare category and tags, you’ll immediately see that category has the additional parameters blank and null both set to True. So that’s what we need to do for tags as well. Amend the model to look like this:

Remember: Always make the effort to create a test to reproduce your bug before fixing it. That way, you know you can catch it in future.

Syntax highlighting

This is one feature that not everyone will want to implement. If you want to be able to show code snippets on your blog, then implementing syntax highlighting is well worth your time. However, if that’s not what you want to use your blog for, feel free to skip over this section.

Now, earlier in the series we implemented Markdown support. In Markdown there are two main ways to denote a code block. One is to indent the code by four spaces, while the other is to use fenced code blocks with syntax highlighting. There are many flavours of Markdown available for Python, and unfortunately the one we’ve been using so far doesn’t support fenced code blocks, so we’ll be switching to one that does.

We also need to be able to generate a suitable stylesheet to highlight the code appropriately. For that, we’ll be using Pygments. So let’s first uninstall our existing implementation of Markdown:

$ pip uninstall Markdown

And install the new modules:

$ pip install markdown2 Pygments

Don’t forget to record the changes:

$ pip freeze > requirements.txt

Now, we need to amend our Markdown template tags to use the new version of Markdown:

All we do here is change the Markdown module that gets imported, and amend how it is called. Note that we pass through the parameter fenced-code-blocks to enable this functionality.

If you now run the development server and create a post with some code in it (just copy the Ruby example from here), then view it on the site, you should be able to see that it’s in a <code> block. However, it’s not highlighted yet. Let’s commit our changes:

Now, if you examine the markup for your code blocks using your browser’s developer tools, you’ll notice that the code is wrapped in many different spans with various classes. Pygments can generate a CSS file that uses those classes to highlight your code.

First, let’s create a folder to store our CSS files in:

$ mkdir blogengine/static/css

Next, we’ll add a blank CSS file for any other styling we may want to apply:

Now, if you run the development server and reload the page, your code will be highlighted using the default Pygments style. If you don’t like it, there are plenty to choose from. Run the following command:

$ pygmentize -L styles

That will list the various styles available. For instance, let’s say we want to try the Tango style:

$ pygmentize -S tango -f html > blogengine/static/css/code.css

If you like the Monokai theme in Sublime Text, there’s a Pygments version of that:

$ pygmentize -S monokai -f html > blogengine/static/css/code.css

If you like the Solarized theme, that’s not bundled with Pygments, but can be installed separately:

Pick one that you like - I’m going to go for the dark version of Solarized.

Note that this doesn’t actually change the background colour of the code blocks. You will therefore need to set this manually using the CSS file we created earlier. If you’re using Solarized Dark like I am, then this should set it correctly:

div.codehilitepre {
background-color: #002b36;
}

If you’re using Solarized Light, then this should be more appropriate:

Whoops! We introduced an error here. If we take a look, we can see that the problem is on line 7, where we import the Markdown module. That makes sense, as we now use a different implementation of Markdown. Fortunately, in Python you can import modules with a different name, which makes this a breeze to fix. Change the line to:

import markdown2 as markdown

Now, if you run your tests, they should pass. It’s important that if a test breaks, you fix it as soon as possible and don’t put it off. Let’s commit these changes:

$ git add blogengine/tests.py
$ git commit -m 'Fixed a broken test'

Our syntax highlighting is now done! If you want to see it in action using the Solarized Dark theme, check out the copy of this blogging engine hosted here.

Tidying up

Now that our blog is up and running on Heroku, it could do with a bit of work on the front end to make it look a bit nicer. If you recall, we’re using Bootstrap for our front end, so you may want to refer to the documentation for that to give you some ideas on how you want to style your blog.

Bootstrap has a nifty pager class for Next and Previous links, so let’s apply that to our post list template: