views:

56

answers:

1

First of all, sorry if this isn't an appropriate question for StackOverflow. I've tried to make it as generalisable as possible.

I want to create a database (MySQL, site running Django) that has users, who can be allocated a certain number of points for various types of action - it's a collaborative game. My requirements are to obtain:

  • the number of points a user has
  • the user's ranking compared to all other users
  • and the overall leaderboard (i.e. all users ranked in order of points)

This is what I have so far, in my Django models.py file:

class SiteUser(models.Model):
    name = models.CharField(max_length=250 )
    email = models.EmailField(max_length=250 )
    date_added = models.DateTimeField(auto_now_add=True) 
    def points_total(self):
        points_added = PointsAdded.objects.filter(user=self)
        points_total = 0
        for point in points_added:
            points_total += point.points
        return points_total

class PointsAdded(models.Model):
    user = models.ForeignKey('SiteUser')
    action = models.ForeignKey('Action')
    date_added = models.DateTimeField(auto_now_add=True) 
    def points(self):
        points = Action.objects.filter(action=self.action)
        return points

class Action(models.Model):
    points = models.IntegerField()
    action = models.CharField(max_length=36)

However it's rapidly becoming clear to me that it's actually quite complex (in Django query terms at least) to figure out the user's ranking and return the leaderboard of users. At least, I'm finding it tough. Is there a more elegant way to do something like this?

This question seems to suggest that I shouldn't even have a separate points table - what do people think? It feels more robust to have separate tables, but I don't have much experience of database design.

A: 

It's a bit more difficult to have points saved in the same table, but it's totally worth it. You can do very simple ordering/filtering operations if you have computed points total on user model. And you can count totals only when something changes (not every time you want to show them). Just put some validation logic into post_save signals and make sure to cover this logic with tests and you're good.

p.s. denormalization on wiki.

Dmitry Shevchenko