It's been a long while since I last updated my old page. Reason was that it was cumbersome even to change small things, since it did not feature a web interface, but required me to login via SSH.
All in all, it was a technically cool solution but rather impractical from a user's point of view. Now, since Django, the Python Web Framework, is getting so much attention recently, I gave it a try at redesigning my old page. In fact, I didn't just want to redesign, but extend it with a blog application.
I started diving into Django without having any idea of Python at all (I do however have several years of experience in PHP and Perl/mod_perl and other MVC web frameworks).
How it is done
Django installation and configuration is pretty well-covered on the Django project site and I won't repeat it here again. I'll assume you've successfully installed Django and created your own project.
My page has a number of sections (top navigation bar), which are all based on Django's internal django.contrib.flatpages. The blog section, on the other hand, is a custom application.
All it needs is the following model:
from django.db import models
class Tag(models.Model):
slug = models.SlugField(prepopulate_from=('title',))
title = models.CharField(maxlength=30)
description = models.TextField(help_text='Short summary of this tag')
def __str__(self):
return self.title
def get_absolute_url(self):
return "/blog/tag/%s/" % self.slug
class Admin:
list_display = ('slug', 'title',)
search_fields = ('title', 'description',)
class Meta:
ordering = ('title',)
class Post(models.Model):
slug = models.SlugField(prepopulate_from=('title',), help_text='Automatically built from the title.'
)
assoc_tags = models.ManyToManyField(Tag)
title = models.CharField(maxlength=80)
date = models.DateTimeField(auto_now_add=True)
body = models.TextField()
image = models.ImageField(
'Attach Image',
upload_to='blog',
blank=True
)
def __str__(self):
return self.title
def get_absolute_url(self):
return "/blog/%s/%s/" % (self.date.strftime("%Y/%b/%d").lower(), self.slug)
class Admin:
list_display = ('slug', 'title', 'date',)
search_fields = ('title', 'body',)
date_hierarchy = 'date'
class Meta:
get_latest_by = 'date'
ordering = ('-date',)
To display the tag list on the right of this page, I used a simple template tag like this:
from django import template
from tsonny.blog.models import Tag
class TagListNode(template.Node):
def __init__(self, varname):
self.varname = varname
def render(self, context):
context[self.varname] = Tag.objects.all()
return ''
def do_get_tag_list(parser, token):
"""
{% get_tag_list as tag_list %}
"""
bits = token.contents.split()
if len(bits) != 3:
raise template.TemplateSyntaxError, "'%s' tag takes two arguments" % bits[0]
if bits[1] != "as":
raise template.TemplateSyntaxError, "First argument to '%s' tag must be 'as'" % bits[0]
return TagListNode(bits[2])
register = template.Library()
register.tag('get_tag_list', do_get_tag_list)
To include the "latest news" from other website's RSS feeds, I simply took the aggregator code from djangoproject.com (it's in the Trac repository) and modified it a bit.
To make life easier, the interested reader may also want to download the complete code, ready to use (but without templates, of course).

