annotate gpp/forums/models.py @ 75:374b24dd2f9a

First checkin of forums. Have noticed cascading delete behavior. Will try to prevent this next.
author Brian Neal <bgneal@gmail.com>
date Sun, 05 Jul 2009 00:03:40 +0000
parents
children e356ea79a7a2
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@75 45 def topic_count_update(self):
bgneal@75 46 """Call to notify the forum that its topic count has been updated."""
bgneal@75 47 self.topic_count = Topic.objects.filter(forum=self).count()
bgneal@75 48
bgneal@75 49 def post_count_update(self):
bgneal@75 50 """Call to notify the forum that its post count has been updated."""
bgneal@75 51 my_posts = Post.objects.filter(topic__forum=self)
bgneal@75 52 self.post_count = my_posts.count()
bgneal@75 53 if self.post_count > 0:
bgneal@75 54 self.last_post = my_posts[self.post_count - 1]
bgneal@75 55 else:
bgneal@75 56 self.last_post = None
bgneal@75 57
bgneal@75 58
bgneal@75 59 class Topic(models.Model):
bgneal@75 60 forum = models.ForeignKey(Forum, related_name='topics')
bgneal@75 61 name = models.CharField(max_length=255)
bgneal@75 62 creation_date = models.DateTimeField(auto_now_add=True)
bgneal@75 63 user = models.ForeignKey(User)
bgneal@75 64 view_count = models.IntegerField(blank=True, default=0)
bgneal@75 65 sticky = models.BooleanField(blank=True, default=False)
bgneal@75 66 locked = models.BooleanField(blank=True, default=False)
bgneal@75 67
bgneal@75 68 # denormalized fields to reduce database hits
bgneal@75 69 post_count = models.IntegerField(blank=True, default=0)
bgneal@75 70 update_date = models.DateTimeField(auto_now=True)
bgneal@75 71 last_post = models.OneToOneField('Post', blank=True, null=True,
bgneal@75 72 related_name='parent_topic')
bgneal@75 73
bgneal@75 74 class Meta:
bgneal@75 75 ordering = ('-sticky', '-update_date', )
bgneal@75 76
bgneal@75 77 def __unicode__(self):
bgneal@75 78 return self.name
bgneal@75 79
bgneal@75 80 def post_count_update(self):
bgneal@75 81 """
bgneal@75 82 Call this function to notify the topic instance that its post count
bgneal@75 83 has changed.
bgneal@75 84 """
bgneal@75 85 my_posts = Post.objects.filter(topic=self)
bgneal@75 86 self.post_count = my_posts.count()
bgneal@75 87 if self.post_count > 0:
bgneal@75 88 self.last_post = my_posts[self.post_count - 1]
bgneal@75 89 self.update_date = self.last_post.creation_date
bgneal@75 90 else:
bgneal@75 91 self.last_post = None
bgneal@75 92 self.update_date = self.creation_date
bgneal@75 93
bgneal@75 94
bgneal@75 95 class Post(models.Model):
bgneal@75 96 topic = models.ForeignKey(Topic, related_name='posts')
bgneal@75 97 user = models.ForeignKey(User, related_name='posts')
bgneal@75 98 creation_date = models.DateTimeField(auto_now_add=True)
bgneal@75 99 update_date = models.DateTimeField(auto_now=True)
bgneal@75 100 body = models.TextField()
bgneal@75 101 html = models.TextField()
bgneal@75 102 user_ip = models.IPAddressField(blank=True, default='')
bgneal@75 103
bgneal@75 104 class Meta:
bgneal@75 105 ordering = ('creation_date', )
bgneal@75 106
bgneal@75 107 def summary(self):
bgneal@75 108 LIMIT = 50
bgneal@75 109 if len(self.body) < LIMIT:
bgneal@75 110 return self.body
bgneal@75 111 return self.body[:LIMIT] + '...'
bgneal@75 112
bgneal@75 113 def __unicode__(self):
bgneal@75 114 return self.summary()
bgneal@75 115
bgneal@75 116 def save(self, *args, **kwargs):
bgneal@75 117 html = render_to_string('forums/post.html', {'data': self.body})
bgneal@75 118 self.html = html.strip()
bgneal@75 119 super(Post, self).save(*args, **kwargs)
bgneal@75 120
bgneal@75 121 def delete(self, *args, **kwargs):
bgneal@75 122 first_post_id = self.topic.posts.all()[0].id
bgneal@75 123 super(Post, self).delete(*args, **kwargs)
bgneal@75 124 if self.id == first_post_id:
bgneal@75 125 self.topic.delete()
bgneal@75 126
bgneal@75 127 # TODO: A "read" table
bgneal@75 128 # TODO: A flagged post table