эффективный подсчет предметов - PullRequest
0 голосов
/ 28 июня 2011

У меня есть 2 модели:

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() 

Так как я всегда хочу показать нет. сообщений по каждой категории, я всегда считаю и сохраняю их каждый раз, когда пользователь создает или удаляет сообщение таким образом:

   ## 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
        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()
        ........

Мой вопрос заключается в том, можем ли мы вместо того, чтобы считать каждый объект, использовать что-то вроде:

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

Или есть лучшее решение!

О, я пропустил это! Я обновил модель поста, чтобы включить отношения!

1 Ответ

1 голос
/ 28 июня 2011

Да, гораздо лучшее решение:

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()

Поскольку вы не указали связь между публикацией и категорией, я догадался о части Count('posts').Возможно, вам придется возиться с этим.

О, и вы захотите избавиться от поля no_of_posts из модели.Это не обязательно с этим.Или вы можете просто изменить имя аннотации.

Вы по-прежнему сможете получать количество сообщений с помощью category.no_of_posts, но вы заставляете базу данных выполнять работу за вас.

...