annotate gpp/bio/models.py @ 318:c550933ff5b6

Fix a bug where you'd get an error when trying to delete a forum thread (topic does not exist). Apparently when you call topic.delete() the posts would get deleted, but the signal handler for each one would run, and it would try to update the topic's post count or something, but the topic was gone? Reworked the code a bit and explicitly delete the posts first. I also added a sync() call on the parent forum since post counts were not getting adjusted.
author Brian Neal <bgneal@gmail.com>
date Sat, 05 Feb 2011 21:46:52 +0000
parents 4d086d2210b9
children 000c006fee97
rev   line source
gremmie@1 1 """
gremmie@1 2 Contains models for the bio application.
gremmie@1 3 I would have picked profile for this application, but that is already taken, apparently.
gremmie@1 4 """
bgneal@277 5 import datetime
gremmie@1 6 import os.path
gremmie@1 7
gremmie@1 8 from django.db import models
bgneal@259 9 from django.contrib.auth.models import User
gremmie@1 10 from django.conf import settings
bgneal@54 11 from django.core.cache import cache
bgneal@277 12 from django.template.loader import render_to_string
gremmie@1 13
bgneal@128 14 from core.markup import SiteMarkup
bgneal@124 15
bgneal@215 16 # These are the secondary user status enumeration values.
bgneal@215 17 (STA_ACTIVE, # User is a full member in good standing.
bgneal@215 18 STA_RESIGNED, # User has voluntarily asked to be removed.
bgneal@215 19 STA_REMOVED, # User was removed for bad behavior.
bgneal@215 20 STA_SUSPENDED, # User is temporarily suspended; e.g. a stranger tripped
bgneal@215 21 # the spam filter.
bgneal@215 22 STA_SPAMMER, # User has been removed for spamming.
bgneal@215 23 STA_STRANGER, # New member, isn't fully trusted yet. Their comments and
bgneal@215 24 # forum posts are scanned for spam. They can have their
bgneal@215 25 # accounts deactivated by moderators for spamming.
bgneal@215 26 ) = range(6)
bgneal@147 27
bgneal@147 28 USER_STATUS_CHOICES = (
bgneal@147 29 (STA_ACTIVE, "Active"),
bgneal@147 30 (STA_RESIGNED, "Resigned"),
bgneal@147 31 (STA_REMOVED, "Removed"),
bgneal@147 32 (STA_SUSPENDED, "Suspended"),
bgneal@147 33 (STA_SPAMMER, "Spammer"),
bgneal@215 34 (STA_STRANGER, "Stranger")
bgneal@147 35 )
bgneal@147 36
bgneal@204 37
bgneal@204 38 class Badge(models.Model):
bgneal@204 39 """This model represents badges that users can earn."""
bgneal@204 40 image = models.ImageField(upload_to='badges')
bgneal@204 41 name = models.CharField(max_length=64)
bgneal@204 42 description = models.TextField(blank=True)
bgneal@204 43 order = models.IntegerField()
bgneal@204 44 numeric_id = models.IntegerField(db_index=True)
bgneal@204 45
bgneal@204 46 class Meta:
bgneal@204 47 ordering = ('order', )
bgneal@204 48
bgneal@204 49 def __unicode__(self):
bgneal@204 50 return self.name
bgneal@204 51
bgneal@204 52 def get_absolute_url(self):
bgneal@204 53 return self.image.url
bgneal@204 54
bgneal@204 55 def html(self):
bgneal@204 56 """Returns a HTML img tag representation of the badge."""
bgneal@204 57 if self.image:
bgneal@204 58 return u'<img src="%s" alt="%s" title="%s" />' % (
bgneal@204 59 self.get_absolute_url(), self.name, self.name)
bgneal@204 60 return u''
bgneal@204 61 html.allow_tags = True
bgneal@204 62
bgneal@204 63
gremmie@1 64 def avatar_file_path_for_user(username, filename):
gremmie@1 65 return os.path.join(settings.AVATAR_DIR, 'users', username, filename)
gremmie@1 66
gremmie@1 67 def avatar_file_path(instance, filename):
gremmie@1 68 return avatar_file_path_for_user(instance.user.username, filename)
gremmie@1 69
gremmie@1 70
gremmie@1 71 class UserProfile(models.Model):
gremmie@1 72 """model to represent additional information about users"""
gremmie@1 73
bgneal@259 74 user = models.ForeignKey(User, unique=True)
gremmie@1 75 location = models.CharField(max_length=128, blank=True)
gremmie@1 76 birthday = models.DateField(blank=True, null=True,
gremmie@1 77 help_text='Optional; the year is not shown to others')
gremmie@1 78 occupation = models.CharField(max_length=128, blank=True)
gremmie@1 79 interests = models.CharField(max_length=255, blank=True)
gremmie@1 80 profile_text = models.TextField(blank=True)
gremmie@1 81 profile_html = models.TextField(blank=True)
gremmie@1 82 hide_email = models.BooleanField(default=True)
gremmie@1 83 signature = models.TextField(blank=True)
gremmie@1 84 signature_html = models.TextField(blank=True)
gremmie@1 85 avatar = models.ImageField(upload_to=avatar_file_path, blank=True)
bgneal@70 86 time_zone = models.CharField(max_length=64, blank=True,
bgneal@70 87 default='US/Pacific')
bgneal@120 88 use_24_time = models.BooleanField(default=False)
bgneal@96 89 forum_post_count = models.IntegerField(default=0)
bgneal@215 90 status = models.IntegerField(default=STA_STRANGER,
bgneal@147 91 choices=USER_STATUS_CHOICES)
bgneal@147 92 status_date = models.DateTimeField(auto_now_add=True)
bgneal@204 93 badges = models.ManyToManyField(Badge, through="BadgeOwnership")
bgneal@277 94 update_date = models.DateTimeField(db_index=True, blank=True)
gremmie@1 95
gremmie@1 96 def __unicode__(self):
gremmie@1 97 return self.user.username
gremmie@1 98
gremmie@1 99 class Meta:
gremmie@1 100 ordering = ('user__username', )
gremmie@1 101
gremmie@1 102 def save(self, *args, **kwargs):
bgneal@282 103 self.update_date = datetime.datetime.now()
bgneal@128 104 sm = SiteMarkup()
bgneal@128 105 self.profile_html = sm.convert(self.profile_text)
bgneal@128 106 self.signature_html = sm.convert(self.signature)
gremmie@1 107 super(UserProfile, self).save(*args, **kwargs)
bgneal@54 108 cache.delete('avatar_' + self.user.username)
bgneal@138 109
bgneal@138 110 @models.permalink
bgneal@138 111 def get_absolute_url(self):
bgneal@138 112 return ('bio-view_profile', (), {'username': self.user.username})
bgneal@138 113
bgneal@204 114 def badge_ownership(self):
bgneal@204 115 if hasattr(self, '_badges'):
bgneal@204 116 return self._badges
bgneal@308 117
bgneal@308 118 cache_key = 'badges-%s' % self.user.username
bgneal@308 119 self._badges = cache.get(cache_key)
bgneal@308 120 if self._badges is not None:
bgneal@308 121 return self._badges
bgneal@308 122
bgneal@204 123 self._badges = BadgeOwnership.objects.filter(profile=self).select_related(
bgneal@204 124 "badge")
bgneal@308 125
bgneal@308 126 cache.set(cache_key, self._badges, 15 * 60)
bgneal@204 127 return self._badges
bgneal@204 128
bgneal@215 129 def is_stranger(self):
bgneal@215 130 """Returns True if this user profile status is STA_STRANGER."""
bgneal@215 131 return self.status == STA_STRANGER
bgneal@215 132
bgneal@215 133 def user_is_active(self):
bgneal@215 134 """Returns the profile's user is_active status. This function exists
bgneal@215 135 for the admin.
bgneal@215 136 """
bgneal@215 137 return self.user.is_active
bgneal@215 138 user_is_active.boolean = True
bgneal@215 139 user_is_active.short_description = "Is Active"
bgneal@215 140
bgneal@223 141 def search_title(self):
bgneal@223 142 full_name = self.user.get_full_name()
bgneal@223 143 if full_name:
bgneal@223 144 return u"%s (%s)" % (self.user.username, full_name)
bgneal@223 145 return self.user.username
bgneal@223 146
bgneal@223 147 def search_summary(self):
bgneal@277 148 text = render_to_string('search/indexes/bio/userprofile_text.txt',
bgneal@277 149 {'object': self});
bgneal@277 150 return text
bgneal@223 151
bgneal@138 152
bgneal@138 153 class UserProfileFlag(models.Model):
bgneal@138 154 """This model represents a user flagging a profile as inappropriate."""
bgneal@259 155 user = models.ForeignKey(User)
bgneal@138 156 profile = models.ForeignKey(UserProfile)
bgneal@138 157 flag_date = models.DateTimeField(auto_now_add=True)
bgneal@138 158
bgneal@138 159 def __unicode__(self):
bgneal@138 160 return u"%s's profile flagged by %s" % (self.profile.user.username,
bgneal@138 161 self.user.username)
bgneal@138 162
bgneal@138 163 class Meta:
bgneal@138 164 ordering = ('flag_date', )
bgneal@138 165
bgneal@138 166 def get_profile_url(self):
bgneal@138 167 return '<a href="%s">Profile</a>' % self.profile.get_absolute_url()
bgneal@138 168 get_profile_url.allow_tags = True
bgneal@204 169
bgneal@204 170
bgneal@204 171 class BadgeOwnership(models.Model):
bgneal@204 172 """This model represents the ownership of badges by users."""
bgneal@204 173 profile = models.ForeignKey(UserProfile)
bgneal@204 174 badge = models.ForeignKey(Badge)
bgneal@204 175 count = models.IntegerField(default=1)
bgneal@204 176
bgneal@204 177 class Meta:
bgneal@204 178 verbose_name_plural = "badge ownership"
bgneal@204 179 ordering = ('badge__order', )
bgneal@204 180
bgneal@204 181 def __unicode__(self):
bgneal@204 182 if self.count == 1:
bgneal@204 183 return u"%s owns 1 %s" % (self.profile.user.username,
bgneal@204 184 self.badge.name)
bgneal@204 185 else:
bgneal@204 186 return u"%s owns %d %s badges" % (self.profile.user.username,
bgneal@204 187 self.count, self.badge.name)
bgneal@204 188
bgneal@204 189 def badge_count_str(self):
bgneal@204 190 if self.count == 1:
bgneal@204 191 return u"1 %s" % self.badge.name
bgneal@204 192 return u"%d %ss" % (self.count, self.badge.name)