David Avraamides Code and other geekery

Yet Another Django Blog

To help me learn Django, I decided to build a blog. It was surprisingly easy. This article walks through my initial version of the site.

I've recently cutover from WordPress to a new blog which I developed using Django. I've been using Django at work for the past month and as I've gotten more familiar with it, I decided building a completely new blog would actually be fun and fairly simple. Besides, I've read about a few other people who have done the same thing and they say the hardest part was converting over their old blog entries. That should be cake for me as I only have a handful of posts to worry about!

If you haven't heard of it yet, Django is a framework for building web applications written in Python. It's an open-source project that spun out of an online news organization and thus has its roots in CMS applications. But it has now grown to support many other kinds of web applications. I stumbled onto Django when I was looking for a better way to build software after using C#/.NET and ASP.NET for the last two years. That led me to Python and I quickly found myself leaving C# behind with no regrets. Once I was sold on Python, I started looking at the "right" way to build web apps in Python. While there really isn't an answer to that question, Django comes pretty darn close.

Building the Blog

After reading the posts above about other Django-based blogs, I sat down to start my own. It took me about an hour to get a first cut of a working blog together, which I think is great, but some people seem fixated on the 15- or 20-minute project. I was basing some of my design on other people's older code base which changed considerably with the "magic-removal" relase so I had to convert things over (using the sophisticated engineering technigue of: refresh the browser, read the error message, fix the code, rinse, repeat).

I started with these fairly basic models for a Tag and a Post which gives you useful enough models for a surprsingly workable blog.

class Tag(models.Model):
    slug = models.SlugField(prepopulate_from=('title',), primary_key=True)
    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',)

A Tag is just really just a unique string used to categorize posts. In hindsight, I could have made this even simpler as I'm really just using a Tag's slug field. A Post is the model that really makes it a blog. Its also pretty simple, with the obvious fields: title, date and body, plus a the many-to-many tags relationship. It also has a slug field which is like a human-readable key to make it easier to refer to an object by a friendly name rather then a number.

class Post(models.Model):
    slug = models.SlugField(prepopulate_from=('title',), primary_key=True)
    tags = models.ManyToManyField(Tag)
    title = models.CharField(maxlength=80)
    date = models.DateTimeField(auto_now_add=True)
    body = models.TextField()

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return "/blog/%s/%s/" % (self.date.strftime("%Y/%m/%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',)

Now that I'm a little more familiar with the problem, I could probably start from scratch and do it again in under 30 minutes, but why? In fact, I think someone should make a video of a real development session with all the typical mistakes and error messages, along with a voice over of how the user figured out the problem from the errors. Now that would be useful.

After getting the basic features done, I started working on the little tweaks that would make it more polished and easy to use. Some of these things came very easy but others were a little trickier. I'll post my comments on some of these features in the near futrue, as the information might be useful to others.


13 Comments

Posted by
Jeff Croft
Monday December 25, 2006
2:18 a.m.

In fact, I think someone should make a video of a real development session with all the typical mistakes and error messages, along with a voice over of how the user figured out the problem from the errors. Now that would be useful.

Great idea! Go for it. :)


Posted by
Park
Tuesday February 13, 2007
10:28 a.m.

Can you license your code with GPL and post it? I'm looking to develop a blog in under 10 minutes (and with your help I can do it...) -Grin-


Posted by
David Avraamides
Tuesday February 13, 2007
10:44 a.m.

Park: While I don't have licensing comments in my source files, I've given public read access to the subversion repository. You're welcome to use whatever you want:

svn co http://davidavraamides.net/svn/da


Posted by
Mo
Thursday June 7, 2007
8:25 a.m.

Ohh boy this one rocks. I'll take your word and hack away on your package. It seriously needed some jumpstart fixes to work for me. And I'm still working to get all the inline database functions to work with sqlite for my testsystem.

Maybe the django tag module (somewhere on googlesource) will replace it in my configuration.

But on another note I quite liked your about page. It's one of the very rare one I like :)

kindest regards, Mo


Posted by
Shawn Weekly
Tuesday July 17, 2007
4:47 p.m.

Thanks a lot for posting this. I am on the brink of jumping into the django world (coming from a .NET background) and will probably borrow quite a bit from folks in the know. Nice to see that people in the django community dog-food their own stuff.


Posted by
Ludvig Ericson
Monday July 23, 2007
7:40 a.m.

Didn't read the whole post but what the hell dude, why are you using the slug for a primary key? Granted it should be unique, but having strings for the main index is just awkward in many ways.

I'd just do unique=True and settle for that.


Posted by
David Avraamides
Monday July 23, 2007
9:04 a.m.

Ludvig: since I use slugs as part of the URL for the article (or name of a tag), it really is the "identifier" for the item. And I don't really see how it's awkward. Why is a unique bit pattern stored as an integer better than a unique bit pattern stored as a string? In fact lots of people use UIDs for database keys these days which are just 32-char strings.

If your argument is about performance, then I think its moot given the activity and traffic on my site ;-)


Posted by
bir2su
Tuesday October 2, 2007
3:20 a.m.

its good to know that people are switching to django to create the website from the scratch. we all love django lets spread it

bir2su.blogspot.com


Posted by
moos3
Wednesday December 12, 2007
11:09 p.m.

does your svn still public, I'm interested in how you did the blog, I'm a php developer lookin into getting started with django, I normally start with a blog app because it normally covers all the things you would ever need to know.


Posted by
David Avraamides
Thursday December 13, 2007
7:57 a.m.

moos3: I added a post, "Subversion Down" to explain this. You can still download a tar file of the code directly from http://davidavraamides.net/static/danet.tgz


Posted by
moos3
Thursday December 13, 2007
8:52 a.m.

Dave: cool thanks, i'm looking forward to looking at the code and breaking it down to learn python. thanks again


Posted by
moos3
Thursday December 13, 2007
9:35 p.m.

i was trying to reuse your markdown code in filter.py but its not returning untruncated text any ideas? on the main page it returns posts truncated but not html of links tho any ideas?


Posted by
David Avraamides
Thursday December 13, 2007
9:55 p.m.

moos3: did you read this post: http://davidavraamides.net/blog/2006/05/23/markdown-support/ ?

I think that may address the problem. Truncating needs to be done intelligently so you don't leave open HTML tags that will muck up your page. Also, in my markdown2html filter, if you are truncating the text, I "clean" it first to remove images, links, and other thinks that could screw up the truncated section (you might have a post that begins with a bunch of images and the truncated version would still take up a lot of space).

It could be smarter, but I choose a simple solution.

Hope this helps.


Closed for comments