gremmie@1: """
gremmie@1: Contains models for the bio application.
gremmie@1: I would have picked profile for this application, but that is already taken, apparently.
gremmie@1: """
bgneal@277: import datetime
gremmie@1: import os.path
gremmie@1: 
gremmie@1: from django.db import models
bgneal@259: from django.contrib.auth.models import User
gremmie@1: from django.conf import settings
bgneal@54: from django.core.cache import cache
bgneal@277: from django.template.loader import render_to_string
gremmie@1: 
bgneal@128: from core.markup import SiteMarkup
bgneal@124: 
bgneal@215: # These are the secondary user status enumeration values. 
bgneal@215: (STA_ACTIVE,        # User is a full member in good standing.
bgneal@215:  STA_RESIGNED,      # User has voluntarily asked to be removed.
bgneal@215:  STA_REMOVED,       # User was removed for bad behavior.
bgneal@215:  STA_SUSPENDED,     # User is temporarily suspended; e.g. a stranger tripped
bgneal@215:                     # the spam filter.
bgneal@215:  STA_SPAMMER,       # User has been removed for spamming.
bgneal@215:  STA_STRANGER,      # New member, isn't fully trusted yet. Their comments and
bgneal@215:                     # forum posts are scanned for spam. They can have their
bgneal@215:                     # accounts deactivated by moderators for spamming.
bgneal@215:  ) = range(6)
bgneal@147: 
bgneal@147: USER_STATUS_CHOICES = (
bgneal@147:     (STA_ACTIVE, "Active"),
bgneal@147:     (STA_RESIGNED, "Resigned"),
bgneal@147:     (STA_REMOVED, "Removed"),
bgneal@147:     (STA_SUSPENDED, "Suspended"),
bgneal@147:     (STA_SPAMMER, "Spammer"),
bgneal@215:     (STA_STRANGER, "Stranger")
bgneal@147: )
bgneal@147: 
bgneal@204: 
bgneal@204: class Badge(models.Model):
bgneal@204:     """This model represents badges that users can earn."""
bgneal@204:     image = models.ImageField(upload_to='badges')
bgneal@204:     name = models.CharField(max_length=64)
bgneal@204:     description = models.TextField(blank=True)
bgneal@204:     order = models.IntegerField()
bgneal@204:     numeric_id = models.IntegerField(db_index=True)
bgneal@204: 
bgneal@204:     class Meta:
bgneal@204:         ordering = ('order', )
bgneal@204: 
bgneal@204:     def __unicode__(self):
bgneal@204:         return self.name
bgneal@204: 
bgneal@204:     def get_absolute_url(self):
bgneal@204:         return self.image.url
bgneal@204: 
bgneal@204:     def html(self):
bgneal@204:         """Returns a HTML img tag representation of the badge."""
bgneal@204:         if self.image:
bgneal@204:             return u'<img src="%s" alt="%s" title="%s" />' % (
bgneal@204:                     self.get_absolute_url(), self.name, self.name)
bgneal@204:         return u''
bgneal@204:     html.allow_tags = True
bgneal@204: 
bgneal@204: 
gremmie@1: def avatar_file_path_for_user(username, filename):
gremmie@1:     return os.path.join(settings.AVATAR_DIR, 'users', username, filename)
gremmie@1: 
gremmie@1: def avatar_file_path(instance, filename):
gremmie@1:     return avatar_file_path_for_user(instance.user.username, filename)
gremmie@1: 
gremmie@1: 
gremmie@1: class UserProfile(models.Model):
gremmie@1:     """model to represent additional information about users"""
gremmie@1: 
bgneal@259:     user = models.ForeignKey(User, unique=True)
gremmie@1:     location = models.CharField(max_length=128, blank=True)
gremmie@1:     birthday = models.DateField(blank=True, null=True,
gremmie@1:             help_text='Optional; the year is not shown to others')
gremmie@1:     occupation = models.CharField(max_length=128, blank=True)
gremmie@1:     interests = models.CharField(max_length=255, blank=True)
gremmie@1:     profile_text = models.TextField(blank=True)
gremmie@1:     profile_html = models.TextField(blank=True)
gremmie@1:     hide_email = models.BooleanField(default=True)
gremmie@1:     signature = models.TextField(blank=True)
gremmie@1:     signature_html = models.TextField(blank=True)
gremmie@1:     avatar = models.ImageField(upload_to=avatar_file_path, blank=True)
bgneal@70:     time_zone = models.CharField(max_length=64, blank=True,
bgneal@70:             default='US/Pacific')
bgneal@120:     use_24_time = models.BooleanField(default=False)
bgneal@96:     forum_post_count = models.IntegerField(default=0)
bgneal@215:     status = models.IntegerField(default=STA_STRANGER,
bgneal@147:             choices=USER_STATUS_CHOICES)
bgneal@147:     status_date = models.DateTimeField(auto_now_add=True)
bgneal@204:     badges = models.ManyToManyField(Badge, through="BadgeOwnership")
bgneal@277:     update_date = models.DateTimeField(db_index=True, blank=True)
gremmie@1: 
gremmie@1:     def __unicode__(self):
gremmie@1:         return self.user.username
gremmie@1: 
gremmie@1:     class Meta:
gremmie@1:         ordering = ('user__username', )
gremmie@1: 
gremmie@1:     def save(self, *args, **kwargs):
bgneal@282:         self.update_date = datetime.datetime.now()
bgneal@128:         sm = SiteMarkup()
bgneal@128:         self.profile_html = sm.convert(self.profile_text)
bgneal@128:         self.signature_html = sm.convert(self.signature)
gremmie@1:         super(UserProfile, self).save(*args, **kwargs)
bgneal@54:         cache.delete('avatar_' + self.user.username)
bgneal@138: 
bgneal@138:     @models.permalink
bgneal@138:     def get_absolute_url(self):
bgneal@138:         return ('bio-view_profile', (), {'username': self.user.username})
bgneal@138: 
bgneal@204:     def badge_ownership(self):
bgneal@204:         if hasattr(self, '_badges'):
bgneal@204:             return self._badges
bgneal@204:         self._badges = BadgeOwnership.objects.filter(profile=self).select_related(
bgneal@204:                 "badge")
bgneal@204:         return self._badges
bgneal@204: 
bgneal@215:     def is_stranger(self):
bgneal@215:         """Returns True if this user profile status is STA_STRANGER."""
bgneal@215:         return self.status == STA_STRANGER
bgneal@215: 
bgneal@215:     def user_is_active(self):
bgneal@215:         """Returns the profile's user is_active status. This function exists
bgneal@215:         for the admin.
bgneal@215:         """
bgneal@215:         return self.user.is_active
bgneal@215:     user_is_active.boolean = True
bgneal@215:     user_is_active.short_description = "Is Active"
bgneal@215: 
bgneal@223:     def search_title(self):
bgneal@223:         full_name = self.user.get_full_name()
bgneal@223:         if full_name:
bgneal@223:             return u"%s (%s)" % (self.user.username, full_name)
bgneal@223:         return self.user.username
bgneal@223: 
bgneal@223:     def search_summary(self):
bgneal@277:         text = render_to_string('search/indexes/bio/userprofile_text.txt',
bgneal@277:                 {'object': self});
bgneal@277:         return text
bgneal@223: 
bgneal@138: 
bgneal@138: class UserProfileFlag(models.Model):
bgneal@138:     """This model represents a user flagging a profile as inappropriate."""
bgneal@259:     user = models.ForeignKey(User)
bgneal@138:     profile = models.ForeignKey(UserProfile)
bgneal@138:     flag_date = models.DateTimeField(auto_now_add=True)
bgneal@138: 
bgneal@138:     def __unicode__(self):
bgneal@138:         return u"%s's profile flagged by %s" % (self.profile.user.username,
bgneal@138:                 self.user.username)
bgneal@138: 
bgneal@138:     class Meta:
bgneal@138:         ordering = ('flag_date', )
bgneal@138: 
bgneal@138:     def get_profile_url(self):
bgneal@138:         return '<a href="%s">Profile</a>' % self.profile.get_absolute_url()
bgneal@138:     get_profile_url.allow_tags = True
bgneal@204: 
bgneal@204: 
bgneal@204: class BadgeOwnership(models.Model):
bgneal@204:     """This model represents the ownership of badges by users."""
bgneal@204:     profile = models.ForeignKey(UserProfile)
bgneal@204:     badge = models.ForeignKey(Badge)
bgneal@204:     count = models.IntegerField(default=1)
bgneal@204: 
bgneal@204:     class Meta:
bgneal@204:         verbose_name_plural = "badge ownership"
bgneal@204:         ordering = ('badge__order', )
bgneal@204: 
bgneal@204:     def __unicode__(self):
bgneal@204:         if self.count == 1:
bgneal@204:             return u"%s owns 1 %s" % (self.profile.user.username,
bgneal@204:                     self.badge.name)
bgneal@204:         else:
bgneal@204:             return u"%s owns %d %s badges" % (self.profile.user.username,
bgneal@204:                     self.count, self.badge.name)
bgneal@204: 
bgneal@204:     def badge_count_str(self):
bgneal@204:         if self.count == 1:
bgneal@204:             return u"1 %s" % self.badge.name
bgneal@204:         return u"%d %ss" % (self.count, self.badge.name)