Well, if fondue is posting an Everygame update, I guess I can, too.

As I've stated a number of times in the past few months, I am still working on Everygame. I'm just waiting at the moment.

I chose the Django project after attempting to write my own prototype from scratch, utilizing nothing more than mod_python. While I managed to cobble together a basic working data model, I realised that it wasn't all that good, and I had a great deal of tasks yet to do. Like a good coder, I decided to look and see what was already written for Python.

Python has two major web frameworks. Turbogears is a package of a number of different pieces of software that, taken together, present a viable web design platform. SQLObject provides a database API, CherryPy communicates with the webserver, Kid is an HTML template system, and MochiKit is a Javascript library.

Django, by contrast, is a more unified whole. This does not mean it is a single monolithic piece of software. On the contrary, loose coupling is a primary design goal. Like Turbogears, it is entirely possible to swap out (for example) the template system for a different one.

However, Django's various components are quite nice, and I am using all of them. Its DB API has one serious drawback, however, which they are fixing in an upcoming version, and which I will describe below.

Let's say you're designing a database model that will act like E2. This means you have a collection of nodes of a variety of types. One of these types might be a document, another might be a user. Both of these have a variety of attributes in common. Most importantly, they share the same database column to represent their unique ID numbers. In this way, a user can enter an ID as part of a URL, and bring up whatever node that ID belongs to. In programming terms, it makes sense to represent these as a hierarchy of classes, with a node class at the root.

         node
        /    \
document      user

The Django DB API does not easily support this concept. First, some terminology: A model is a Python class that maps to a database table. The three classes mentioned above would each be their own model. The Django DB API is largely concerned with how the coder accesses models.

In the current version (0.91) of the Django API, subclassing a model results in a new model (and, thus, a new database table) that looks just like the first one. This is a problem. Because the two models use two completely separate tables, they use two different ID columns, and so their IDs will clash, and the user cannot enter an ID as a URL and look up a node. So the way Django 0.91 can represent this is with something called a OneToOneField.

This is an attribute of a model that replaces the usual ID, and uses an ID from another model instead, which is exactly what we want. Our models might look something like this:

class Node(meta.Model):
    # the id field is implied
    title = meta.CharField(maxlength=100)

class Document(meta.Model):
    node = meta.OneToOneField(Node)
    content = meta.TextField()

class User(meta.Model):
    node = meta.OneToOneField(Node)
    password = meta.CharField(maxlength=30)

The trouble is that an instance of (say) Document uses two models: Node and Document. If we have an instance of Node and we want the "content" attribute of its associated Document, we need to say:

node.get_document().content

Ewwwww! This gets even more disgusting as soon as we try to relate nodes to one another.

This is not just a syntactic ugliness. The fact that these are two different models has important semantic consequences. For example, it is possible that we won't always know when we have a Node and when we have a Document, even if we are referring to the same conceptual node. This can rapidly get very confusing.

Version 0.95 of Django will implement this approximately the same way that SQLObject does, with something called model inheritance. Now, when one model inherits from another, it is implemented as a one-to-one relationship:

class Node(models.Model):
    # the id field is still implied
    title = models.CharField(maxlength=100)

class Document(Node):
    content = models.TextField()

class User(Node):
    password = models.CharField(maxlength=30)

An instance of Document, then, is a single model with both a title attribute and a content attribute. Additionally, Document's title attribute is stored in Node's database table, content is in Document's own table, and (most importantly!) its id attribute is keyed to Node's.

That ugly line of code above is now simply written as:

node.content

This is the primary reason I am waiting until version 0.95 of Django before I do more serious development of Everygame.


Q: Why not just use SQLObject?

A: No one actually asked this, but it is worth explaining anyway.

It is entirely possible to use SQLObject in place of Django's DB API. It supports this feature, among others. However, by using a DB API other than Django's own, I lose Django's wonderful built-in admin app. I also lose any add-on Django apps that I may wish to integrate in the future. Additionally, I rather like Django's DB API, and have no desire to use something else.


Source: Django wiki entry on model inheritance