Very early on, when I was still playing with the look and layout of the website, I asked my friend Lisa. At the time, I was still just running the django development server. Anyway, Lisa has a great mind for web standards and the evolution of web markup. So she immediately picked up on the fact that my pages had a doctype of Transitional HTML 4.01 and gave me quite a bit of a lecture on things I should do instead. She recommended going with at least strict HTML 4.01, but preferably with XHTML. At the time, I wasn't sure what any of that meant (and I'm even still learning my way through it).
So, anyway, I launched the website a few weeks later, with a few things not quite working the way they should have been. Content types were one of those things. One of the first bugs that got reported was by James Rowe: he saw, in my atom feed, that lists and block quotes and other things had embedded paragraph tags (<p>...</p>). And so in some cases, I had nested paragraph tags. Here's what happened. In Django's admin, when you have a text field, you just type in plain text, and then do stuff in the template code to make it render as you need to. In your template, you could just do something like the following:
{{ body }}
That will output the contents of the body field in to the page. The problem is that it will all render as one long line, which does nobody any good, really. I'm sure there are ways to fix that using HTML and CSS, but the easier route (at the time) for me was to instead do:
{{ body|linebreaks }}
Now, it parsed through the contents of the body text field and inserted paragraph tags around paragraphs. The problem is that I got paragraph tags around block quotes and code blocks and lists and so on. Altogether it was a fairly frustrating thing. It was then that I re-read various posts on the b-list and realised that James Bennett is using Markdown for a reason.
I decided to look into these other markup languages, and looked at examples for markdown, textile, and ReST. Of the three, ReST looks like the most complicated and more full of features. Arguably, I don't think I need all of that (and with non-technical bloggers, I don't need to have them learn all sorts of esoteric stuff like that -- they just want to write). That left Textile and Markdown.
I settled on Markdown at the end because its syntax is a lot simpler (especially the extended block quote syntax). The only negative thing I have to say about markdown is that I have to use HTML to create abbreviations. Textile has really nice syntax for that. Supposedly I can extend markdown to behave how I need it to, but I have not yet dived into that. If there's pre-existing code out there, I'd rather just employ that.
Anyway, to get back on track for this post: all three have processors in python that convert the markup to XHTML. As soon as I read that, I remembered my conversation with Lisa, and ran back into IRC to ask her all sorts of newbie questions. A few hours later, after having rediscovered the W3C validator, I was serving out pages with the appropriate markup and appropriate content type tags.
To make things easy, instead of doing the markdown conversion to XHTML on the fly in the templates like this:
{{ body|markdown }}
I redid my blog entry models to have two body tags: one for the markdown text that I enter, and another one to hold the converted XHTML marked up content. So, essentially, when the model's save() function is called, the body gets converted to XHTML again. The model's source code is at the link above in Part 2 of this series, for you to see. But really that method is best illustrated on Django's Wiki.
The doctype definitions are handled in one template file, which I call base.html, which looks very much like this:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>{% stuff %}</head>
</body>{% stuff %}</body>
</html>
If there really is interest about the templates, I am more than happy to dedicate a post to that with more of the source in it.
To make sure that the correct content type headers were being sent, I just added this line into my settings.py file:
DEFAULT_CONTENT_TYPE='application/xhtml+xml'
So, doing that resulted in modern browsers receiving my pages as they should. Broken browsers (like IE6, which still doesn't actually display this site correctly) couldn't show anything on my site. So, some google searches later, I found Sune Kirkeby's middleware code that changes the content types being sent to the browser. It also converts the page to HTML 4.01 Strict if the browser does not accept the 'application/xhtml+xml' doctype.
And there you have it, I'm now serving out strict XHTML 1.1 pages (I hope!) wherever and whenever possible. The natural segue, then, is toward microformats which I'll talk about in the next episode.
3 Comments
Seemant,
Great series of posts on building out your blog using Django. I also wanted to just say hi, as the Django community in Boston is small.
We use Django for all our sites at Compete.
Cheers, David
Nice to hear you're using the same basic Django setup for I do,
as I am currently developing one to learn Django. And yeah, markdown is really nice - I just wonder how less technical writers would cope with it ...
Greetings, Klaus
Hi David,
Is the Compete main site also done in django? It's so nice to see that the Django community is growing as fast as it is and that Django is penetrating all sorts of web development.
Klaus,
I actually think markdown is the best of the bunch for non-technical people, because it is so intuitive. ReST may well be the most powerful markup language, but anything that requires more than one document to even begin to understand it, gets automatically ruled out for simplicity.
That leaves us with markdown and textile, and it's almost a toss-up, to be honest; Neither one, however, seems capable of doing a strong emphasis, though (without html markup to help it along).
I'm currently hacking up a markdown extension to help me with the microformats on this site, though, so my opinion on markdown may well change ;).