annotate gpp/forums/models.py @ 96:93d9e74a471e

Forums: added forum post counts for each user in the user profile.
author Brian Neal <bgneal@gmail.com>
date Sun, 13 Sep 2009 18:43:08 +0000
parents 62af8cd8f57b
children 96eec1ed0fd3
rev   line source
bgneal@75 1 """
bgneal@75 2 Models for the forums application.
bgneal@75 3 """
bgneal@75 4 from django.db import models
bgneal@75 5 from django.contrib.auth.models import User, Group
bgneal@75 6 from django.template.loader import render_to_string
bgneal@75 7
bgneal@75 8
bgneal@75 9 class Category(models.Model):
bgneal@75 10 name = models.CharField(max_length=80)
bgneal@75 11 slug = models.SlugField(max_length=80)
bgneal@75 12 position = models.IntegerField(blank=True, default=0)
bgneal@75 13 groups = models.ManyToManyField(Group, blank=True, null=True,
bgneal@75 14 help_text="If groups are assigned to this category, only members" \
bgneal@75 15 " of those groups can view this category.")
bgneal@75 16
bgneal@75 17 class Meta:
bgneal@75 18 ordering = ('position', )
bgneal@75 19 verbose_name_plural = 'Categories'
bgneal@75 20
bgneal@75 21 def __unicode__(self):
bgneal@75 22 return self.name
bgneal@75 23
bgneal@75 24
bgneal@75 25 class Forum(models.Model):
bgneal@75 26 category = models.ForeignKey(Category, related_name='forums')
bgneal@75 27 name = models.CharField(max_length=80)
bgneal@75 28 slug = models.SlugField(max_length=80)
bgneal@75 29 description = models.TextField(blank=True, default='')
bgneal@75 30 position = models.IntegerField(blank=True, default=0)
bgneal@75 31 moderators = models.ManyToManyField(Group, blank=True, null=True)
bgneal@75 32
bgneal@75 33 # denormalized fields to reduce database hits
bgneal@75 34 topic_count = models.IntegerField(blank=True, default=0)
bgneal@75 35 post_count = models.IntegerField(blank=True, default=0)
bgneal@75 36 last_post = models.OneToOneField('Post', blank=True, null=True,
bgneal@75 37 related_name='parent_forum')
bgneal@75 38
bgneal@75 39 class Meta:
bgneal@75 40 ordering = ('position', )
bgneal@75 41
bgneal@75 42 def __unicode__(self):
bgneal@75 43 return self.name
bgneal@75 44
bgneal@81 45 @models.permalink
bgneal@81 46 def get_absolute_url(self):
bgneal@81 47 return ('forums-forum_index', [self.slug])
bgneal@81 48
bgneal@75 49 def topic_count_update(self):
bgneal@75 50 """Call to notify the forum that its topic count has been updated."""
bgneal@75 51 self.topic_count = Topic.objects.filter(forum=self).count()
bgneal@75 52
bgneal@75 53 def post_count_update(self):
bgneal@75 54 """Call to notify the forum that its post count has been updated."""
bgneal@75 55 my_posts = Post.objects.filter(topic__forum=self)
bgneal@75 56 self.post_count = my_posts.count()
bgneal@75 57 if self.post_count > 0:
bgneal@75 58 self.last_post = my_posts[self.post_count - 1]
bgneal@75 59 else:
bgneal@75 60 self.last_post = None
bgneal@75 61
bgneal@75 62
bgneal@75 63 class Topic(models.Model):
bgneal@75 64 forum = models.ForeignKey(Forum, related_name='topics')
bgneal@75 65 name = models.CharField(max_length=255)
bgneal@75 66 creation_date = models.DateTimeField(auto_now_add=True)
bgneal@75 67 user = models.ForeignKey(User)
bgneal@75 68 view_count = models.IntegerField(blank=True, default=0)
bgneal@75 69 sticky = models.BooleanField(blank=True, default=False)
bgneal@75 70 locked = models.BooleanField(blank=True, default=False)
bgneal@75 71
bgneal@75 72 # denormalized fields to reduce database hits
bgneal@75 73 post_count = models.IntegerField(blank=True, default=0)
bgneal@75 74 update_date = models.DateTimeField(auto_now=True)
bgneal@75 75 last_post = models.OneToOneField('Post', blank=True, null=True,
bgneal@75 76 related_name='parent_topic')
bgneal@75 77
bgneal@75 78 class Meta:
bgneal@75 79 ordering = ('-sticky', '-update_date', )
bgneal@75 80
bgneal@75 81 def __unicode__(self):
bgneal@75 82 return self.name
bgneal@75 83
bgneal@82 84 @models.permalink
bgneal@82 85 def get_absolute_url(self):
bgneal@82 86 return ('forums-topic_index', [self.pk])
bgneal@82 87
bgneal@75 88 def post_count_update(self):
bgneal@75 89 """
bgneal@75 90 Call this function to notify the topic instance that its post count
bgneal@75 91 has changed.
bgneal@75 92 """
bgneal@75 93 my_posts = Post.objects.filter(topic=self)
bgneal@75 94 self.post_count = my_posts.count()
bgneal@75 95 if self.post_count > 0:
bgneal@75 96 self.last_post = my_posts[self.post_count - 1]
bgneal@75 97 self.update_date = self.last_post.creation_date
bgneal@75 98 else:
bgneal@75 99 self.last_post = None
bgneal@75 100 self.update_date = self.creation_date
bgneal@75 101
bgneal@83 102 def reply_count(self):
bgneal@83 103 """
bgneal@83 104 Returns the number of replies to a topic. The first post
bgneal@83 105 doesn't count as a reply.
bgneal@83 106 """
bgneal@83 107 if self.post_count > 1:
bgneal@83 108 return self.post_count - 1
bgneal@83 109 return 0
bgneal@83 110
bgneal@75 111
bgneal@75 112 class Post(models.Model):
bgneal@75 113 topic = models.ForeignKey(Topic, related_name='posts')
bgneal@75 114 user = models.ForeignKey(User, related_name='posts')
bgneal@75 115 creation_date = models.DateTimeField(auto_now_add=True)
bgneal@75 116 update_date = models.DateTimeField(auto_now=True)
bgneal@75 117 body = models.TextField()
bgneal@75 118 html = models.TextField()
bgneal@83 119 user_ip = models.IPAddressField(blank=True, default='', null=True)
bgneal@75 120
bgneal@75 121 class Meta:
bgneal@96 122 ordering = ('-creation_date', )
bgneal@75 123
bgneal@91 124 @models.permalink
bgneal@91 125 def get_absolute_url(self):
bgneal@91 126 return ('forums-goto_post', [self.pk])
bgneal@91 127
bgneal@75 128 def summary(self):
bgneal@75 129 LIMIT = 50
bgneal@75 130 if len(self.body) < LIMIT:
bgneal@75 131 return self.body
bgneal@75 132 return self.body[:LIMIT] + '...'
bgneal@75 133
bgneal@75 134 def __unicode__(self):
bgneal@75 135 return self.summary()
bgneal@75 136
bgneal@75 137 def save(self, *args, **kwargs):
bgneal@75 138 html = render_to_string('forums/post.html', {'data': self.body})
bgneal@75 139 self.html = html.strip()
bgneal@75 140 super(Post, self).save(*args, **kwargs)
bgneal@75 141
bgneal@75 142 def delete(self, *args, **kwargs):
bgneal@75 143 first_post_id = self.topic.posts.all()[0].id
bgneal@75 144 super(Post, self).delete(*args, **kwargs)
bgneal@75 145 if self.id == first_post_id:
bgneal@75 146 self.topic.delete()
bgneal@75 147
bgneal@75 148 # TODO: A "read" table
bgneal@75 149 # TODO: A flagged post table