/dinette/models.py
Python | 375 lines | 372 code | 3 blank | 0 comment | 0 complexity | 1f0a4594688ccf8174da7774c40556ed MD5 | raw file
- from django.db import models
- from django.contrib.auth.models import User, Group
- from django.conf import settings
- from django.contrib.sites.models import Site
- from django.template.defaultfilters import slugify
- from django.db.models.signals import post_save
- from django.template.defaultfilters import truncatewords
- from django.core.urlresolvers import reverse
- import hashlib
- from BeautifulSoup import BeautifulSoup
- import datetime
- from dinette.libs.postmarkup import render_bbcode
- from markupfield.fields import MarkupField
- class SiteConfig(models.Model):
- name = models.CharField(max_length = 100)
- tag_line = models.TextField(max_length = 100)
- class SuperCategory(models.Model):
- name = models.CharField(max_length = 100)
- description = models.TextField(default='')
- ordering = models.PositiveIntegerField(default = 1)
- created_on = models.DateTimeField(auto_now_add=True)
- updated_on = models.DateTimeField(auto_now=True)
- posted_by = models.ForeignKey(User)
- accessgroups = models.ManyToManyField(Group, related_name='can_access_forums')
-
- class Meta:
- verbose_name = "Super Category"
- verbose_name_plural = "Super Categories"
- ordering = ('-ordering', 'created_on')
-
- def __unicode__(self):
- return self.name
-
-
- class Category(models.Model):
- name = models.CharField(max_length = 100)
- slug = models.SlugField(max_length = 110)
- description = models.TextField(default='')
- ordering = models.PositiveIntegerField(default = 1)
- super_category = models.ForeignKey(SuperCategory)
- created_on = models.DateTimeField(auto_now_add=True)
- updated_on = models.DateTimeField(auto_now=True)
- posted_by = models.ForeignKey(User, related_name='cposted')
- moderated_by = models.ManyToManyField(User, related_name='moderaters')
-
- class Meta:
- verbose_name = "Category"
- verbose_name_plural = "Categories"
- ordering = ('ordering','-created_on')
-
- def save(self, *args, **kwargs):
- if not self.slug:
- slug = slugify(self.name)
- same_slug_count = Category.objects.filter(slug__startswith = slug).count()
- if same_slug_count:
- slug = slug + str(same_slug_count)
- self.slug = slug
- super(Category, self).save(*args, **kwargs)
-
- def get_absolute_url(self):
- return reverse("dinette_index", args=[self.slug])
-
- def getCategoryString(self):
- return "category/%s" % self.slug
-
- def noofPosts(self):
- count = 0
- for topic in self.get_topics():
- #total posts for this topic = total replies + 1 (1 is for the topic as we are considering it as topic)
- count += topic.reply_set.count() + 1
- return count
-
- def lastPostDatetime(self):
- ''' we are assuming post can be topic / reply
- we are finding out the last post / (if exists) last reply datetime '''
- return self.lastPost().created_on
-
- def lastPostedUser(self):
- ''' we are assuming post can be topic / reply
- we are finding out the last post / (if exists) last reply datetime '''
- return self.lastPost().posted_by
-
- def lastPost(self):
- if(self.ftopics_set.count() == 0):
- return self
- obj = self.ftopics_set.order_by('-created_on')[0]
- if (obj.reply_set.count() > 0 ):
- return obj.reply_set.order_by("-created_on")[0]
- else :
- return obj
-
- def get_topics(self):
- return Ftopics.objects.filter(category=self)
- def __unicode__(self):
- return self.name
-
- class TopicManager(models.Manager):
- use_for_related_fields = True
- def get_queryset(self):
- return super(TopicManager, self).get_queryset().filter(is_hidden = False)
-
- def get_new_since(self, when):
- "Topics with new replies after @when"
- now = datetime.datetime.now()
- return self.filter(last_reply_on__gt = now)
-
- class Ftopics(models.Model):
- category = models.ForeignKey(Category)
- posted_by = models.ForeignKey(User)
- subject = models.CharField(max_length=999)
- slug = models.SlugField(max_length = 200, db_index = True)
- message = MarkupField(default_markup_type=getattr(settings,
- 'DEFAULT_MARKUP_TYPE',
- 'markdown'),
- markup_choices=settings.MARKUP_RENDERERS,
- escape_html=True,
- )
- file = models.FileField(upload_to='dinette/files',default='',null=True,blank=True)
- attachment_type = models.CharField(max_length=20,default='nofile')
- filename = models.CharField(max_length=100,default="dummyname.txt")
- viewcount = models.IntegerField(default=0)
- replies = models.IntegerField(default=0)
- created_on = models.DateTimeField(auto_now_add=True)
- updated_on = models.DateTimeField(auto_now=True)
- last_reply_on = models.DateTimeField(auto_now_add=True)
- num_replies = models.PositiveSmallIntegerField(default = 0)
-
- #Moderation features
- announcement_flag = models.BooleanField(default=False)
- is_closed = models.BooleanField(default=False)
- is_sticky = models.BooleanField(default=False)
- is_hidden = models.BooleanField(default=False)
-
- # use TopicManager as default, prevent leaking of hidden topics
- default = models.Manager()
- objects = TopicManager()
- # for topic subscriptions
- subscribers = models.ManyToManyField(User, related_name='subscribers')
-
- class Meta:
- ordering = ('-is_sticky', '-last_reply_on',)
- get_latest_by = ('created_on')
- verbose_name = "Topic"
- verbose_name_plural = "Topics"
-
- def save(self, *args, **kwargs):
- if not self.slug:
- slug = slugify(self.subject)
- slug = slug[:198]
- same_slug_count = Ftopics.objects.filter(slug__startswith = slug).count()
- if same_slug_count:
- slug = slug + str(same_slug_count)
- self.slug = slug
- super(Ftopics, self).save(*args, **kwargs)
-
- def __unicode__(self):
- return self.subject
-
- def get_absolute_url(self):
- return reverse('dinette_topic_detail', kwargs={'categoryslug':self.category.slug, 'topic_slug': self.slug})
-
- def htmlfrombbcode(self):
- if(len(self.message.raw.strip()) > 0):
- return render_bbcode(self.message.raw)
- else :
- return ""
-
- def search_snippet(self):
- msg = "%s %s"% (self.subject, self.message.rendered)
- return truncatewords(msg, 50)
-
- def getTopicString(self):
- #which is helpful for doing reverse lookup of an feed url for a topic
- return "topic/%s" % self.slug
-
- def lastPostDatetime(self):
- return self.lastPost().created_on
-
- def lastPostedUser(self):
- return self.lastPost().posted_by.username
-
- def lastPost(self):
- if (self.reply_set.count() == 0):
- return self
- return self.reply_set.order_by('-created_on')[0]
-
- def classname(self):
- return self.__class__.__name__
-
- class ReplyManager(models.Manager):
- use_for_related_fields = True
- def get_queryset(self):
- return super(ReplyManager, self).get_queryset().filter(topic__is_hidden=False)
- # Create Replies for a topic
- class Reply(models.Model):
- topic = models.ForeignKey(Ftopics)
- posted_by = models.ForeignKey(User)
- message = MarkupField(default_markup_type=getattr(settings,
- 'DEFAULT_MARKUP_TYPE',
- 'markdown'),
- markup_choices=settings.MARKUP_RENDERERS,
- escape_html=True,
- )
- file = models.FileField(upload_to='dinette/files',default='',null=True,blank=True)
- attachment_type = models.CharField(max_length=20,default='nofile')
- filename = models.CharField(max_length=100,default="dummyname.txt")
-
- reply_number = models.SmallIntegerField()
- created_on = models.DateTimeField(auto_now_add=True)
- updated_on = models.DateTimeField(auto_now=True)
-
- # replies for hidden topics should be hidden as well
- default = models.Manager()
- objects = ReplyManager()
- class Meta:
- verbose_name = "Reply"
- verbose_name_plural = "Replies"
- ordering = ('created_on',)
- get_latest_by = ('created_on', )
-
- def save(self, *args, **kwargs):
- if not self.pk:
- self.reply_number = self.topic.reply_set.all().count() + 1
- super(Reply, self).save(*args, **kwargs)
-
- def __unicode__(self):
- return truncatewords(self.message, 10)
-
- def search_snippet(self):
- msg = "%s %s"%(self.message.rendered, self.topic.subject)
- return truncatewords(msg, 100)
-
-
- @models.permalink
- def get_absolute_url(self):
- return ('dinette_topic_detail',(),{'categoryslug':self.topic.category.slug,'topic_slug': self.topic.slug})
-
- def get_url_with_fragment(self):
- page = (self.reply_number-1)/settings.REPLY_PAGE_SIZE + 1
- url = self.get_absolute_url()
- if not page == 1:
- return "%s?page=%s#%s" % (url, page, self.reply_number)
- else:
- return "%s#%s" % (url, self.reply_number)
-
-
- def htmlfrombbcode(self):
- soup = BeautifulSoup(self.message.raw)
- #remove all html tags from the message
- onlytext = ''.join(soup.findAll(text=True))
-
- #get the bbcode for the text
- if(len(onlytext.strip()) > 0):
- return render_bbcode(onlytext)
- else :
- return ""
-
- def classname(self):
- return self.__class__.__name__
-
-
- class DinetteUserProfile(models.Model):
- user = models.OneToOneField(User)
- last_activity = models.DateTimeField(auto_now_add=True)
- #When was the last session. Used in page activity since last session.
- last_session_activity = models.DateTimeField(auto_now_add=True)
- userrank = models.CharField(max_length=30, default="Junior Member")
- last_posttime = models.DateTimeField(auto_now_add=True)
- photo = models.ImageField(upload_to='dinette/files', null=True, blank=True)
- signature = models.CharField(max_length = 1000, null = True, blank = True)
- slug = models.SlugField(max_length=200, db_index=True, unique=True)
- is_subscribed_to_digest = models.BooleanField(default=False)
-
- def __unicode__(self):
- return self.user.username
-
- #Populate the user fields for easy access
- @property
- def username(self):
- return self.user.username
-
- @property
- def first_name(self):
- return self.user.first_name
-
- @property
- def last_name(self):
- return self.user.last_name
-
- def get_total_posts(self):
- print self.user.ftopics_set.count() + self.user.reply_set.count()
- return self.user.ftopics_set.count() + self.user.reply_set.count()
-
- def is_online(self):
- from django.conf import settings
- last_online_duration = getattr(settings, 'LAST_ONLINE_DURATION', 900)
- now = datetime.datetime.now()
- if (now - self.last_activity).seconds < last_online_duration:
- return True
- return False
- def getMD5(self):
- m = hashlib.md5()
- m.update(self.user.email)
- return m.hexdigest()
-
- def get_since_last_visit(self):
- "Topics with new relies since last visit"
- return Ftopics.objects.get_new_since(self.last_session_activity)
-
- @models.permalink
- def get_absolute_url(self):
- return ('dinette_user_profile', [self.slug])
-
- def save(self, *args, **kwargs):
- if not self.slug:
- slug = slugify(self.user.username)
- if slug:
- same_slug_count = self._default_manager.filter(slug__startswith=slug).count()
- if same_slug_count:
- slug = slug + str(same_slug_count)
- self.slug = slug
- else:
- #fallback to user id
- slug = self.user.id
- super(DinetteUserProfile, self).save(*args, **kwargs)
-
- class NavLink(models.Model):
- title = models.CharField(max_length = 100)
- url = models.URLField()
-
- class Meta:
- verbose_name = "Navigation Link"
- verbose_name_plural = "Navigation Links"
-
- def __unicode__(self):
- return self.title
-
-
- def create_user_profile(sender, instance, created, **kwargs):
- if created:
- DinetteUserProfile.objects.create(user=instance)
-
- def update_topic_on_reply(sender, instance, created, **kwargs):
- if created:
- instance.topic.last_reply_on = instance.created_on
- instance.topic.num_replies += 1
- instance.topic.save()
- def notify_subscribers_on_reply(sender, instance, created, **kwargs):
- if created:
- site = Site.objects.get_current()
- subject = "%s replied on %s" %(instance.posted_by, instance.topic.subject)
- body = instance.message.rendered
- from_email = getattr(settings, 'DINETTE_FROM_EMAIL', '%s notifications <admin@%s>' %(site.name, site.domain))
- # exclude the user who posted this, even if he is subscribed
- for subscriber in instance.topic.subscribers.exclude(username=instance.posted_by.username):
- subscriber.email_user(subject, body, from_email)
- post_save.connect(create_user_profile, sender=User)
- post_save.connect(update_topic_on_reply, sender=Reply)
- post_save.connect(notify_subscribers_on_reply, sender=Reply)