annotate gpp/forums/models.py @ 81:e356ea79a7a2

More work on forums. Committing what we got so far.
author Brian Neal <bgneal@gmail.com>
date Sun, 23 Aug 2009 00:14:52 +0000
parents 374b24dd2f9a
children bc3978f023c2
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@75 84 def post_count_update(self):
bgneal@75 85 """
bgneal@75 86 Call this function to notify the topic instance that its post count
bgneal@75 87 has changed.
bgneal@75 88 """
bgneal@75 89 my_posts = Post.objects.filter(topic=self)
bgneal@75 90 self.post_count = my_posts.count()
bgneal@75 91 if self.post_count > 0:
bgneal@75 92 self.last_post = my_posts[self.post_count - 1]
bgneal@75 93 self.update_date = self.last_post.creation_date
bgneal@75 94 else:
bgneal@75 95 self.last_post = None
bgneal@75 96 self.update_date = self.creation_date
bgneal@75 97
bgneal@75 98
bgneal@75 99 class Post(models.Model):
bgneal@75 100 topic = models.ForeignKey(Topic, related_name='posts')
bgneal@75 101 user = models.ForeignKey(User, related_name='posts')
bgneal@75 102 creation_date = models.DateTimeField(auto_now_add=True)
bgneal@75 103 update_date = models.DateTimeField(auto_now=True)
bgneal@75 104 body = models.TextField()
bgneal@75 105 html = models.TextField()
bgneal@75 106 user_ip = models.IPAddressField(blank=True, default='')
bgneal@75 107
bgneal@75 108 class Meta:
bgneal@75 109 ordering = ('creation_date', )
bgneal@75 110
bgneal@75 111 def summary(self):
bgneal@75 112 LIMIT = 50
bgneal@75 113 if len(self.body) < LIMIT:
bgneal@75 114 return self.body
bgneal@75 115 return self.body[:LIMIT] + '...'
bgneal@75 116
bgneal@75 117 def __unicode__(self):
bgneal@75 118 return self.summary()
bgneal@75 119
bgneal@75 120 def save(self, *args, **kwargs):
bgneal@75 121 html = render_to_string('forums/post.html', {'data': self.body})
bgneal@75 122 self.html = html.strip()
bgneal@75 123 super(Post, self).save(*args, **kwargs)
bgneal@75 124
bgneal@75 125 def delete(self, *args, **kwargs):
bgneal@75 126 first_post_id = self.topic.posts.all()[0].id
bgneal@75 127 super(Post, self).delete(*args, **kwargs)
bgneal@75 128 if self.id == first_post_id:
bgneal@75 129 self.topic.delete()
bgneal@75 130
bgneal@75 131 # TODO: A "read" table
bgneal@75 132 # TODO: A flagged post table