views:

142

answers:

2

Hello,

I want to store events in a web application I am fooling around with and I feel quite unsure about the pros and cons of each respective approach - using inheritance extensively or in a more modest manner.

Example:

class Event(models.Model):
    moment = models.DateTimeField()

class UserEvent(Event):
    user = models.ForeignKey(User)
    class Meta:
        abstract = True

class UserRegistrationEvent(UserEvent):
    pass # Nothing to add really, the name of the class indicates it's type

class UserCancellationEvent(UserEvent):
    reason = models.CharField()

It feels like I'm creating database tables like crazy. It would require alot of joins to select things out and might complicate querying. But it's design feels nice, I think.

Would it be more reasonable to use a "flatter" model that just has more fields?

class Event(models.Model):
    moment = models.DateTimeField()
    user = models.ForeignKey(User, blank=True, null=True)
    type = models.CharField() # 'Registration', 'Cancellation' ...
    reason = models.CharField(blank=True, null=True)

Thanks for your comments on this, anyone.

Philip

+5  A: 

Flat is better than nested. I don't see that the "deep inheritance" is really buying you anything in this case: I'd go for the flatter model as a simpler, plainer design, with likely better performance characteristics and ease of access.

Alex Martelli
For this specific example, I fully agree. I would start to think about inheritance only if a UserRegistrationEvent, for example, had a whole bunch of data fields on it that were not applicable to a regular Event. And even in that case, I'd give some thought to using abstract base models instead of multi-table inheritance.
Carl Meyer
A: 

You might want to try Abstract base models. This implements inheritance without joins, by only creating tables for the derived classes, containing fields from both the parent and the derived model. This would allow you to keep your nested design, without the performance penalty of all those joins.

Daniel Roseman