views:

266

answers:

3

Let's say I have such model

class Event(models.Model)
    users_count = models.IntegerField(default=0)
    users = models.ManyToManyField(User)

How would you recommend to update users_count value if Event add/delete some users ?

A: 

There is a "design pattern" for that.

Pretty much, override save() and delete().

As they mention, using listeners is also an option, but for this scenario I tend to like the override mechanism better.

celopes
PS. That link is for a really useful collection of mechanisms for accomplishing things using Django. They are not really Design Patterns. But the site is useful none-the-less.
celopes
override save() and delete() will not help with many-to-many relationship
Pydev UA
+1  A: 

Overriding save() may not help you because the update to the M2M is not atomic and happens after the save of the Event instance (I haven't studied the delete() semantics but they are probably similar). This was discussed in another thread.

People are talking about and working on this problem. The best solution I have seen so far is this MonkeyPatch by gregoirecachet. I don't know if this will make it into 1.2 or not. Probably not since the Release Manager (James Bennett) is trying to get people to respect the freeze dates (a major one just passed).

Peter Rowell
+1: I didn't even read the model close enough to see the M2M relationship. And the info on this answer is very useful.
celopes
+1  A: 

If possible in your case, you could introduce Participation model which would join Event and User:

class Participation(models.Model):
    user = models.ForeignKey(User)
    event = models.ForeignKey(Event)

class Event(models.Model):
    users = models.ManyToManyField(User, through='Participation')

And handle pre_save signal sent by Participation to update instance.event counts. It would simplify handling of m2m significantly. And in most cases, it turns out later on that some logic and data fits best in the middle model. If that's not your case, try a custom solution (you should not have many code paths adding Users to Events anyway).

kibitzer