07.03.2010 21:39

  1. koshak

    0 ↑
    0 ↓
    Здравствуйте,
    Я в django, да и в python новичок, поэтому хотел спросить, правильно ли делать например так:
    class Category(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_pk = models.IntegerField()

    content_object = generic.GenericForeignKey(ct_field="content_type", fk_field="object_pk")

    comments_count = models.IntegerField(blank=True, default=0)
    topics_count = models.IntegerField(blank=True, default=0)
    title = models.CharField(max_length=255)
    desc = models.CharField(max_length=500)


    class Topic(models.Model):
    category = models.ForeignKey(Category)
    title = models.CharField(max_length=255)
    desc = models.CharField(max_length=500)
    content = models.CharField(max_length=1000)
    _comments_count = models.IntegerField(blank=True, default=0, db_column='comments_count')

    @property
    def comments_count(self):
    return self._comments_count

    @comments_count.setter
    def comments_count(self, value):
    self.category.comments_count = self.category.comments_count + value - self._comments_count
    self.category.save()
    self._comments_count = value
    Т.е. что бы при изменении кол-ва коментариев топика, изменялось и количество коментариев категории.
  2. Java? :-)

    Нет, в Питоне такие вещи не приняты. То, что вы хотите, в Джанге лучше выразить так:

    from django.db.models import Sum
    
    class Category(models.Model):
        comment_count = models.IntegerField(blank=True, default=0)
    
        def update_comment_count(self):
            aggregate = self.comment_set.aggregate(Sum('comment_count'))
            self.comment_count = aggregate['comment_count__sum']
            self.save()
    
    class Topic(models.Model):
        category = models.ForeignKey(Category)
        comment_count = models.IntegerField(blank=True, default=0, db_column='comments_count')
    
        def save(self, **kwargs):
            super(Topic, self).save(**kwargs)
            self.category.update_comment_count()
    

    То есть:

    • неявная обработка на присваивание обычно не приветствуется, особенно такая нетривиальная: она не только лезет в базу, а ещё и меняет её
    • пересчётом своих данных занимается категория, а не её топик, топик только явно сигналит наверх
    • пересчёт происходит на момент сохранения топика, потому что джанговский ORM не строится из предположения, что всё меняется мгновенно, глобально и неявно, он всегда требует явных действий для изменения данных
    • пересчёт всегда идёт полностью, а не инкрементально, иначе вы попадаете на проблемы с race-condition'ами
  3. koshak

    0 ↑
    0 ↓
    Спасибо, так действительно намного красивее получается.

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.