Mercurial > public > sg101
comparison gpp/forums/models.py @ 100:eb9f99382476
Forums: groups support. Some experimentation with select_related() to reduce queries. There are more opportunities for this, see the TODO comments in views.py.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Tue, 15 Sep 2009 03:15:20 +0000 |
parents | d0d779dd0832 |
children | e67c4dd98db5 |
comparison
equal
deleted
inserted
replaced
99:10d6182b9f6e | 100:eb9f99382476 |
---|---|
1 """ | 1 """ |
2 Models for the forums application. | 2 Models for the forums application. |
3 """ | 3 """ |
4 from django.db import models | 4 from django.db import models |
5 from django.db.models import Q | |
5 from django.contrib.auth.models import User, Group | 6 from django.contrib.auth.models import User, Group |
6 from django.template.loader import render_to_string | 7 from django.template.loader import render_to_string |
7 | 8 |
8 | 9 |
9 class Category(models.Model): | 10 class Category(models.Model): |
11 """ | |
12 Forums belong to a category, whose access may be assigned to groups. | |
13 """ | |
10 name = models.CharField(max_length=80) | 14 name = models.CharField(max_length=80) |
11 slug = models.SlugField(max_length=80) | 15 slug = models.SlugField(max_length=80) |
12 position = models.IntegerField(blank=True, default=0) | 16 position = models.IntegerField(blank=True, default=0) |
13 groups = models.ManyToManyField(Group, blank=True, null=True, | 17 groups = models.ManyToManyField(Group, blank=True, null=True, |
14 help_text="If groups are assigned to this category, only members" \ | 18 help_text="If groups are assigned to this category, only members" \ |
19 verbose_name_plural = 'Categories' | 23 verbose_name_plural = 'Categories' |
20 | 24 |
21 def __unicode__(self): | 25 def __unicode__(self): |
22 return self.name | 26 return self.name |
23 | 27 |
28 def can_access(self, user): | |
29 """ | |
30 Checks to see if the given user has permission to access | |
31 this category. | |
32 If this category has no groups assigned to it, return true. | |
33 Else, return true if the user belongs to a group that has been | |
34 assigned to this category, and false otherwise. | |
35 """ | |
36 if self.groups.count() == 0: | |
37 return True | |
38 if user.is_authenticated(): | |
39 return self.groups.filter(user__pk=user.id).count() > 0 | |
40 return False | |
41 | |
42 | |
43 class ForumManager(models.Manager): | |
44 """ | |
45 The manager for the Forum model. Provides a centralized place to | |
46 put commonly used and useful queries. | |
47 """ | |
48 | |
49 def forums_for_user(self, user): | |
50 """ | |
51 Returns a queryset containing the forums that the given user can | |
52 "see" due to authenticated status, superuser status and group membership. | |
53 """ | |
54 if user.is_superuser: | |
55 qs = self.all() | |
56 else: | |
57 user_groups = [] | |
58 if user.is_authenticated(): | |
59 user_groups = user.groups.all() | |
60 | |
61 qs = self.filter(Q(category__groups__isnull=True) | \ | |
62 Q(category__groups__in=user_groups)) | |
63 | |
64 return qs.select_related('category', 'last_post', 'last_post__user') | |
65 | |
24 | 66 |
25 class Forum(models.Model): | 67 class Forum(models.Model): |
68 """ | |
69 A forum is a collection of topics. | |
70 """ | |
26 category = models.ForeignKey(Category, related_name='forums') | 71 category = models.ForeignKey(Category, related_name='forums') |
27 name = models.CharField(max_length=80) | 72 name = models.CharField(max_length=80) |
28 slug = models.SlugField(max_length=80) | 73 slug = models.SlugField(max_length=80) |
29 description = models.TextField(blank=True, default='') | 74 description = models.TextField(blank=True, default='') |
30 position = models.IntegerField(blank=True, default=0) | 75 position = models.IntegerField(blank=True, default=0) |
33 # denormalized fields to reduce database hits | 78 # denormalized fields to reduce database hits |
34 topic_count = models.IntegerField(blank=True, default=0) | 79 topic_count = models.IntegerField(blank=True, default=0) |
35 post_count = models.IntegerField(blank=True, default=0) | 80 post_count = models.IntegerField(blank=True, default=0) |
36 last_post = models.OneToOneField('Post', blank=True, null=True, | 81 last_post = models.OneToOneField('Post', blank=True, null=True, |
37 related_name='parent_forum') | 82 related_name='parent_forum') |
83 | |
84 objects = ForumManager() | |
38 | 85 |
39 class Meta: | 86 class Meta: |
40 ordering = ('position', ) | 87 ordering = ('position', ) |
41 | 88 |
42 def __unicode__(self): | 89 def __unicode__(self): |
59 else: | 106 else: |
60 self.last_post = None | 107 self.last_post = None |
61 | 108 |
62 | 109 |
63 class Topic(models.Model): | 110 class Topic(models.Model): |
111 """ | |
112 A topic is a thread of discussion, consisting of a series of posts. | |
113 """ | |
64 forum = models.ForeignKey(Forum, related_name='topics') | 114 forum = models.ForeignKey(Forum, related_name='topics') |
65 name = models.CharField(max_length=255) | 115 name = models.CharField(max_length=255) |
66 creation_date = models.DateTimeField(auto_now_add=True) | 116 creation_date = models.DateTimeField(auto_now_add=True) |
67 user = models.ForeignKey(User) | 117 user = models.ForeignKey(User) |
68 view_count = models.IntegerField(blank=True, default=0) | 118 view_count = models.IntegerField(blank=True, default=0) |
108 return self.post_count - 1 | 158 return self.post_count - 1 |
109 return 0 | 159 return 0 |
110 | 160 |
111 | 161 |
112 class Post(models.Model): | 162 class Post(models.Model): |
163 """ | |
164 A post is an instance of a user's single contribution to a topic. | |
165 """ | |
113 topic = models.ForeignKey(Topic, related_name='posts') | 166 topic = models.ForeignKey(Topic, related_name='posts') |
114 user = models.ForeignKey(User, related_name='posts') | 167 user = models.ForeignKey(User, related_name='posts') |
115 creation_date = models.DateTimeField(auto_now_add=True) | 168 creation_date = models.DateTimeField(auto_now_add=True) |
116 update_date = models.DateTimeField(auto_now=True) | 169 update_date = models.DateTimeField(auto_now=True) |
117 body = models.TextField() | 170 body = models.TextField() |