kennethkam.com

Furthering A Simple Django Blog

The last entry talked about using virtualenv, simple git commands, and a simple model and URLconf for the blog application. This entry will focus on Django contrib packages, which provide free RSS, a sitemap, generic comments, and many more.

Django’s got what you need

Django has a lot more than an ORM and some URL routing. A casual peek inside django.contrib will reveal many add-on apps that provide additional functionality where most websites will find useful. Apart from the default contrib apps, kennethkam.com uses comments, flatpages, humanize, markup, sitemaps, and syndication.

humanize and markup are template filters that provides formatting niceties to text. For example, markup has a markdown filter plus codehilite.

{{ entry.text|markdown:"codehilite" }}

I would consult Django’s contrib documentation for further usage. For now, I want to talk about how kennethkam.com implemented the other contrib apps.

Comments are for free

Django’s generic comments framework is easy to work with. To hook this up with your model, all you need is a bit of templatetag magic. Load comments and pass your object to the templatetag to hook it up.

{% load comments %}
{% get_comment_list for object as comment_list %}
{% for comment in comment_list %}
    ...
{% endfor %}

Rendering the form is no problem.

{# continuing from the above example #}
{% get_comment_form for object as form %}
{{ form }}

The default form for the comments app required the email field, but not the name of the poster. I wanted the opposite, so I customized the comments framework (documentation). I started by creating a comments app and added forms.py to the app. I copied the templatetags folder from the default comments app into my own app. Now to work on the form.

from django.contrib.comments.forms import CommentForm
from django import forms
from django.utils.translation import ugettext_lazy as _

class CommentFormRequireName(CommentForm):

    email = forms.EmailField(label=_("Email address"), required=False)
    name = forms.CharField(label=_("Name"), max_length=50, required=True)

I subclassed the default CommentForm, copied the lines for the two fields I wanted to change, and passed the required keyword argument. Simple.

To finish, I added the setting COMMENTS_APP = 'kennethkam.comments' and implemented get_form method in the __init__.py of my comments app. This is well documented in the Django documentation.

The world is flatpages

Flatpages are ideal for one-off content. kennethkam.com uses flatpages for the about and Taipei 2009 Trip Report. Flatpages allow you to to define your own templates for each ‘flatpage’.

Implementing it takes 3 steps from a default Django project:

  1. Add 'django.contrib.flatpages' to INSTALLED_APPS setting
  2. Add 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware' to the MIDDLEWARE_CLASSES setting.
  3. Run python manage.py syncdb and you’re done.

You can start editing your flatpages in the admin.

Sitemap for Google

Django comes with awesome support for generating XML sitemaps. See the documentation for more information. I used the default GenericSitemap and FlatPageSitemap for my Entry model and my flatpages, as mentioned above.

I defined a custom sitemap that described the categories pages.

from django.contrib.sitemaps import Sitemap
from django.core import urlresolvers
from tagging.models import Tag

class TagSitemap(Sitemap):
    changefreq = "monthly"
    priority = 0.3

    def items(self):
        return Tag.objects.all()

    def location(self, obj):
        return urlresolvers.reverse("category", args=(obj.name,))

All there is to it is subclass the Sitemap class and defining two methods: items() and location().

Syndication

This is the easiest contrib I have used for my blog. All I needed to do is to add a line to my URLconf and define the feed_dict for the line above.

feeds = {
    "latest": LatestEntries
}

(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', \
    {'feed_dict': feeds}),

LatestEntries is a subclass of Feed, defined in feeds.py, which lives in my blog app.

from django.contrib.syndication.feeds import Feed
from kennethkam.blog.models import Entry

class LatestEntries(Feed):
    title = 'Latest Entries on kennethkam.com'
    link = '/'
    description = 'Latest blog entries on kennethkam.com'
    author_name = 'Kenneth Kam'

    def items(self):
        return Entry.objects.exclude(draft=True)[:10]

You can grab the working feed here.

A working simple blog

This is all I needed to do for a simple working weblog. It runs nicely at the moment. In hindsight, I am more satisfied with this setup than your average Wordpress install. At least I get to play around in Django a bit.

I will talk about Fabric and more git topics, but I think they merit their own entry instead of sharing it with the contribs, so they will be here in the future.

Comments

  • There are no comments.

Add a Comment