PageRenderTime 25ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/lbforum/models.py

http://github.com/vicalloy/LBForum
Python | 287 lines | 275 code | 11 blank | 1 comment | 0 complexity | 9ef9184d35366dc374278a4af232bd3d MD5 | raw file
  1. # -*- coding: UTF-8 -*-
  2. from __future__ import unicode_literals
  3. from django.db import models
  4. from django.db.models.signals import post_save
  5. from django.utils.translation import ugettext_lazy as _
  6. from django.conf import settings
  7. from easy_thumbnails.fields import ThumbnailerImageField
  8. from easy_thumbnails.files import get_thumbnailer
  9. from el_pagination import settings as elp_setttings
  10. from django.utils.encoding import python_2_unicode_compatible
  11. from lbattachment.models import LBAttachment
  12. @python_2_unicode_compatible
  13. class Category(models.Model):
  14. name = models.CharField(max_length=100)
  15. descn = models.TextField(blank=True)
  16. oid = models.PositiveIntegerField(default=999)
  17. created_on = models.DateTimeField(auto_now_add=True)
  18. updated_on = models.DateTimeField(blank=True, null=True)
  19. class Meta:
  20. verbose_name = _("Category")
  21. verbose_name_plural = _("Categories")
  22. ordering = ('-oid', 'created_on')
  23. def __str__(self):
  24. return self.name
  25. @python_2_unicode_compatible
  26. class Forum(models.Model):
  27. name = models.CharField(max_length=100)
  28. slug = models.SlugField(max_length=110)
  29. description = models.TextField(default='')
  30. oid = models.PositiveIntegerField(default=999)
  31. category = models.ForeignKey(Category)
  32. admins = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True)
  33. created_on = models.DateTimeField(auto_now_add=True)
  34. updated_on = models.DateTimeField(blank=True, null=True)
  35. num_topics = models.IntegerField(default=0)
  36. num_posts = models.IntegerField(default=0)
  37. last_post = models.ForeignKey(
  38. 'Post', models.SET_NULL,
  39. verbose_name=_('Last post'),
  40. blank=True, null=True)
  41. class Meta:
  42. verbose_name = _("Forum")
  43. verbose_name_plural = _("Forums")
  44. ordering = ('oid', '-created_on')
  45. permissions = (
  46. ("sft_mgr_forum", _("Forum-Administrator")),
  47. )
  48. def __str__(self):
  49. return self.name
  50. def _count_nums_topic(self):
  51. return self.topic_set.all().count()
  52. def _count_nums_post(self):
  53. return Post.objects.filter(topic__forum=self).count()
  54. @models.permalink
  55. def get_absolute_url(self):
  56. return ('lbforum_forum', (), {'forum_slug': self.slug})
  57. def update_state_info(self, last_post=None, commit=True):
  58. self.num_topics = self._count_nums_topic()
  59. self.num_posts = self._count_nums_post()
  60. if not last_post:
  61. last_post = Post.objects.filter(
  62. topic__forum=self).order_by('-created_on').first()
  63. self.last_post = last_post
  64. if commit:
  65. self.save()
  66. def is_admin(self, user):
  67. if user.has_perm('lbforum.sft_mgr_forum'):
  68. return True
  69. return self.admins.filter(pk=user.pk).exists()
  70. @python_2_unicode_compatible
  71. class TopicType(models.Model):
  72. forum = models.ForeignKey(Forum, verbose_name=_('Forum'))
  73. name = models.CharField(max_length=100)
  74. slug = models.SlugField(max_length=100)
  75. description = models.TextField(blank=True)
  76. def __str__(self):
  77. return self.name
  78. LEVEL_CHOICES = (
  79. (30, _('Default')),
  80. (60, _('Distillate')),
  81. )
  82. @python_2_unicode_compatible
  83. class Topic(models.Model):
  84. forum = models.ForeignKey(Forum, verbose_name=_('Forum'))
  85. topic_type = models.ForeignKey(
  86. TopicType, verbose_name=_('Topic Type'),
  87. blank=True, null=True)
  88. posted_by = models.ForeignKey(settings.AUTH_USER_MODEL)
  89. post = models.ForeignKey(
  90. 'Post', verbose_name=_('Post'),
  91. related_name='topics', blank=True, null=True)
  92. subject = models.CharField(max_length=999)
  93. num_views = models.IntegerField(default=0)
  94. num_replies = models.PositiveSmallIntegerField(default=0)
  95. created_on = models.DateTimeField(auto_now_add=True)
  96. updated_on = models.DateTimeField(blank=True, null=True)
  97. last_reply_on = models.DateTimeField(auto_now_add=True)
  98. last_post = models.ForeignKey(
  99. 'Post', models.SET_NULL,
  100. verbose_name=_('Last post'),
  101. related_name='last_post_topics', blank=True, null=True)
  102. has_imgs = models.BooleanField(default=False)
  103. has_attachments = models.BooleanField(default=False)
  104. need_replay = models.BooleanField(default=False) # need_reply :-)
  105. need_reply_attachments = models.BooleanField(default=False)
  106. closed = models.BooleanField(default=False)
  107. sticky = models.BooleanField(default=False)
  108. hidden = models.BooleanField(default=False)
  109. level = models.SmallIntegerField(choices=LEVEL_CHOICES, default=30)
  110. class Meta:
  111. ordering = ('-last_reply_on',) # '-sticky'
  112. get_latest_by = ('created_on')
  113. verbose_name = _("Topic")
  114. verbose_name_plural = _("Topics")
  115. def __str__(self):
  116. return self.subject
  117. def _count_nums_replies(self):
  118. return self.posts.filter(topic_post=False).count()
  119. @models.permalink
  120. def get_absolute_url(self):
  121. return ('lbforum_topic', (), {'topic_id': self.id})
  122. def has_replied(self, user):
  123. if user.is_anonymous():
  124. return False
  125. return Post.objects.filter(posted_by=user, topic=self).count()
  126. def update_state_info(self, last_post=None, commit=True):
  127. self.num_replies = self._count_nums_replies()
  128. if not last_post:
  129. last_post = self.posts.order_by('-created_on').first()
  130. self.last_post = last_post
  131. if commit:
  132. self.save()
  133. @python_2_unicode_compatible
  134. class Post(models.Model):
  135. FORMAT_CHOICES = (
  136. ('bbcode', _('BBCode')),
  137. ('markdown', _('Markdown')),
  138. ('html', _('Html')),
  139. )
  140. topic = models.ForeignKey(Topic, verbose_name=_('Topic'), related_name='posts')
  141. posted_by = models.ForeignKey(settings.AUTH_USER_MODEL)
  142. poster_ip = models.GenericIPAddressField()
  143. topic_post = models.BooleanField(default=False)
  144. format = models.CharField(max_length=20, default='bbcode', choices=FORMAT_CHOICES)
  145. message = models.TextField()
  146. attachments = models.ManyToManyField(LBAttachment, blank=True)
  147. has_imgs = models.BooleanField(default=False)
  148. has_attachments = models.BooleanField(default=False)
  149. created_on = models.DateTimeField(auto_now_add=True)
  150. updated_on = models.DateTimeField(blank=True, null=True)
  151. last_updated_by = models.ForeignKey(
  152. settings.AUTH_USER_MODEL,
  153. related_name='last_updated_by_posts',
  154. blank=True, null=True)
  155. class Meta:
  156. verbose_name = _("Post")
  157. verbose_name_plural = _("Posts")
  158. ordering = ('-created_on',)
  159. get_latest_by = ('created_on', )
  160. def __str__(self):
  161. return self.message[:80]
  162. def subject(self):
  163. if self.topic_post:
  164. return _('Topic: %s') % self.topic.subject
  165. return _('Re: %s') % self.topic.subject
  166. def file_attachments(self):
  167. return self.attachments.filter(is_img=False)
  168. def img_attachments(self):
  169. return self.attachments.filter(is_img=True)
  170. def _update_attachments_flag(self):
  171. self.has_attachments = self.attachments.filter(is_img=False).exists()
  172. self.has_imgs = self.attachments.filter(is_img=True).exists()
  173. self.save()
  174. if self.topic_post:
  175. topic = self.topic
  176. topic.has_attachments = self.has_attachments
  177. topic.has_imgs = self.has_imgs
  178. topic.save()
  179. def update_attachments(self, attachment_ids):
  180. self.attachments = LBAttachment.objects.filter(pk__in=attachment_ids)
  181. self._update_attachments_flag()
  182. @models.permalink
  183. def get_absolute_url(self):
  184. return ('lbforum_post', (), {'post_id': self.pk})
  185. def get_absolute_url_ext(self):
  186. topic = self.topic
  187. post_idx = topic.posts.filter(created_on__lte=self.created_on).count()
  188. page = (post_idx - 1) / elp_setttings.PER_PAGE + 1
  189. return '%s?page=%s#p%s' % (topic.get_absolute_url(), page, self.pk)
  190. @python_2_unicode_compatible
  191. class LBForumUserProfile(models.Model):
  192. user = models.OneToOneField(
  193. settings.AUTH_USER_MODEL, related_name='lbforum_profile',
  194. verbose_name=_('User'))
  195. nickname = models.CharField(
  196. _("Nickname"), max_length=255, blank=False, default='')
  197. avatar = ThumbnailerImageField(_("Avatar"), upload_to='imgs/avatars', blank=True, null=True)
  198. bio = models.TextField(blank=True)
  199. def __str__(self):
  200. return self.nickname or self.user.username
  201. def get_total_topics(self):
  202. return self.user.topic_set.count()
  203. def get_total_posts(self):
  204. return self.user.post_set.count()
  205. def get_absolute_url(self):
  206. return self.user.get_absolute_url()
  207. def get_avatar_url(self, size=48):
  208. if not self.avatar:
  209. return '%s%s' % (settings.STATIC_URL, 'lbforum/imgs/avatar.png', )
  210. options = {'size': (size, size), 'crop': True}
  211. return get_thumbnailer(self.avatar).get_thumbnail(options).url
  212. def get_large_avatar_url(self):
  213. return self.get_avatar_url(80)
  214. def create_user_profile(sender, instance, created, **kwargs):
  215. if created:
  216. LBForumUserProfile.objects.create(user=instance)
  217. def update_last_post(sender, instance, created, **kwargs):
  218. post = instance
  219. if created:
  220. topic = instance.topic
  221. forum = topic.forum
  222. topic.update_state_info(last_post=post)
  223. forum.update_state_info(last_post=post)
  224. # post_save.connect(create_user_profile, sender=User)
  225. post_save.connect(update_last_post, sender=Post)