views:

54

answers:

2

Hello,

I'm trying to design models for a forum I wish to create in Django.

So far I have:

class Forum(models.Model):
    name = models.CharField(max_length=255)
    slug = models.SlugField(max_length=150)
    description = models.TextField()

    def __unicode__(self):
        return self.name

class SubForum(models.Model):
    parent_forum = models.ForeignKey('Forum', related_name='forums')
    parent = models.ForeignKey('self', blank=True, null=True, related_name='children')
    name = models.CharField(max_length=300)
    slug = models.SlugField(max_length=150)
    description = models.TextField()

    def __unicode__(self):
        if self.parent:
            return u'%s: %s - %s' % (self.parent_forum.name,
                                     self.parent.name,
                                     self.name)
        return u'%s: %s' % (self.parent_forum.name, self.name)

This works for the most part as I am able to choose a parent category although I am not sure how to select parent of a child's parent. For example if I had the following:

Grandparent -> Parent -> Child

How would I select Grandparent from Child?

This kind of hierarchy also makes the Django admin rather messy as it doesn't cascade in an orderly fashion. Do I have to build the entire admin from scratch in order to organise this into a usable interface?

Lastly the __unicode__ function in the SubForum model allows me to print the parent but what about a grandparent. Can I get __unicode__ to print all ancestors?

Thanks.

A: 

I would simply create one Forum model that can either have another Forum as it's parent, or have a null parent. Then if you want to print out all parents you could use a while loop like this pseudocode:

heirarchy = ""
f = this forum model
while f.parent is not null:
   heirarchy.append(f.parent.name)
   f = f.parent

to answer the other part of your question, in order to select a child while knowing the parent id, you would query Django's object structure like so:

Forum.objects.filter(parent=PARENT_ID)

and to get the grandparent of a child you would do:

forum_object.parent.parent
Josiah
+4  A: 

What you want to do is to build a tree, or better yet hierarchy and traverse it. I suggest using MPTT over adjacency list model to build it. Both are techniques for easy manipulation and storage of such structures.

As for django implementation of MPTT try django-mptt.

Misc: nice article hierarchical data database design.

rebus
@rebus: I read that article whilst doing research on a tagging system.I was hoping that I wouldn't have to deviate from the django.core too much.Thanks for your answer, it's worth considering but I don't see the pitfalls of adjacency lists being a large problem. There wouldn't be more than 100 forums in any case and those taxing JOIN queries could be kept in a cache.Don't you think?
Anarchist
@Anarchist Well, it's just that MPTT is easier to select and adjacency is easier to update and my guess is your gonna do more selects and less updates, thus the recommendation of MPTT, but both will suite you just fine and i doubt you should have any speed related issues on such small dataset.
rebus