开发者

effective counting of objects

I have 2 models:

Category(models.Model):
    name = models.CharField(max_length=30)
    no_of_posts = models.IntegerField(default=0) # a denormalised field to store post count

Post(models.Model):
    category = models.ForeignKey(Category)
    title = models.CharField(max_length=100)
    desc = models.TextField()
    user = models.ForeignKey(User)
    pub_date = models.DateTimeField(null=True, blank=True)  
    first_save = models.BooleanField() 

Since I always want to show the no. of posts alongwith each category, I always count & store them every time a user creates or deletes a post this way:

   ## inside Post model ##
   def save(self):  
      if not pub_date and first_save:
        pub_date = datetime.datetime.now()
        # counting & saving category posts when a post is 1st published
        category = self.category
开发者_StackOverflow        super(Post, self).save()
        category.no_of_posts = Post.objects.filter(category=category).count()
        category.save()

   def delete(self): 
        category = self.category
        super(Post, self).delete()
        category.no_of_posts = Post.objects.filter(category=category).count()
        category.save()
        ........

My question is whether, instead of counting every object, can we not use something like:

 category.no_of_posts += 1 // in save() # and
 category.no_of_posts -= 1 // in delete()

Or is there a better solution!

Oh, I missed that! I updated the post model to include the relationship!


Yes, a much better solution:

from django.db.models import Count

class CategoryManager(models.Manager):
    def get_query_set(self, *args, **kwargs):
        qs = super(CategoryManager, self).get_query_set(*args, **kwargs)
        return qs.annotate(no_of_posts=Count('post'))

class Category(models.Model):
    ...
    objects = CategoryManager()

Since you didn't show the relationship between Post and Category, I guessed on the Count('posts') part. You might have to fiddle with that.

Oh, and you'll want to get rid of the no_of_posts field from the model. It's not necessary with this. Or, you can just change the name of the annotation.

You'll still be able to get the post count with category.no_of_posts but you're making the database do the legwork for you.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜