简体   繁体   中英

Django: Count of ManyToMany field in PositiveIntegerField during save() in a models.py

I want to alter the count of a ManyToMany Field during save of my model. For which I modified the save(). If I run save(), count will not be updated. If I run save second time without updating the field it will update the count.

class UserProfile(models.Model):

    follower = models.ManyToManyField('self', related_name='Followers',
        blank=True, symmetrical=False)
    following = models.ManyToManyField('self', related_name='Followings',
        blank=True, symmetrical=False)
    follower_count = models.PositiveIntegerField(null=True, blank=True,
        editable=False)
    following_count = models.PositiveIntegerField(null=True, blank=True,
        editable=False)

    class Meta:
        verbose_name = 'User Profile'
        verbose_name_plural = 'User Profiles'

    def __str__(self):
        return self.follower_count

    def save(self, *args, **kwargs):
        super(UserProfile, self).save(*args, **kwargs)
        self.following_count = self.following.all().count()

        self.follower_count = self.follower.all().count()
        super(UserProfile, self).save(*args, **kwargs)

I want to update count with save().

 def save(self, *args, **kwargs):
        self.following_count = self.following.all().count()
        super(UserProfile, self).save(*args, **kwargs)

Get the count first and then call save method

You can omit the first save, like:

def save(self, *args, **kwargs):
    self.following_count = self.following.count()
    self.follower_count = self.follower.count()
    super(UserProfile, self)

That being said, I'm not entirely sure that the above is a good idea for several reasons:

  1. it makes "saving" a computationally expensive function, since you make two extra aggregates;
  2. it is likely that between two saves, the number of followers/followings will not change;
  3. if you remove/add followers/followings, you do not trigger the number of followers/followings automatically. Therefore at certain times, the counts will not be correct.

If performance is not an issue both fields can be turned into properties that calculate the value on every access

class UserProfile(models.Model):

    follower = models.ManyToManyField('self', related_name='Followers',
        blank=True, symmetrical=False)
    following = models.ManyToManyField('self', related_name='Followings',
        blank=True, symmetrical=False)

    @cached_property
    def follower_count(self):
        return self.follower.count()

    @cached_property
    def following_count(self):
        return self.following.count()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM