Mc-
Mc-

Reputation: 4056

Choosing best Django architecture for scalability / performance

I had a doubt on how to architecture the model.

I want to give some entities the possibility to be voted, in this case, a paper. I came up with this two possibilities:

Option 1:

Link the entity as a relationship

class Vote(model.Model):
    author = models.ForeignKey(User)

    created = models.DateField(auto_now=True)
    value = models.IntegerField(default=1)


class Paper(models.Model):
    author = models.ForeignKey(User)
    edition = models.ForeignKey(ConferenceEdition)

    votes = models.OneToMany(Vote)

advantages:

Desavantages:

Option 2:

Not to link the class

class Vote(model.Model):
    author = models.ForeignKey(User)

    created = models.DateField(auto_now=True)
    value = models.IntegerField(default=1)

    entity_id = models.IntegerField()
    entity_type = models.CharField(max_length=255,default='Paper')


class Paper(models.Model):
    author = models.ForeignKey(User)
    edition = models.ForeignKey(ConferenceEdition)

    num_votes = models.IntegerField(default=0)

Avantages:

Desavantages:

Option 3:

I'm listening

Thanks!

Upvotes: 1

Views: 448

Answers (1)

Jure C.
Jure C.

Reputation: 3080

Django loads many to many fields only if you explicitly call them.

So in your 1st case:

paper.votes.all()

If you want to load all the votes when doing your query, you can in django 1.4 do prefetch_related

paper = Paper.objects.get(pk=1).prefetch_related('votes')

By the way, instead of .all() you can use .count(), which generates a different database query that is much faster since it only has to count values, instead of retrieve them into django/python.

There is also a third approach:

You coud have extra field in your model: votes_count, that you would update on pre_save(), and it would hold that value for you. This way you get both: you can query for all votes, but you can also just grab a number.

Upvotes: 4

Related Questions