models.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. from urlparse import urlparse
  2. from django.db import models
  3. from django.dispatch import receiver
  4. from django.utils.translation import ugettext_lazy as _
  5. from mptt.managers import TreeManager
  6. from mptt.models import MPTTModel, TreeForeignKey
  7. from misago.acl import version as acl_version
  8. from misago.acl.models import BaseRole
  9. from misago.core import serializer
  10. from misago.core.signals import secret_key_changed
  11. from misago.core.utils import subset_markdown, slugify
  12. FORUMS_TREE_ID = 1
  13. class ForumManager(TreeManager):
  14. def private_threads(self):
  15. return self.get(special_role='private_threads')
  16. def root_category(self):
  17. return self.get(special_role='root_category')
  18. def all_forums(self, include_root=False):
  19. qs = self.filter(tree_id=FORUMS_TREE_ID)
  20. if not include_root:
  21. qs = self.filter(lft__gt=3)
  22. return qs.order_by('lft')
  23. class Forum(MPTTModel):
  24. parent = TreeForeignKey(
  25. 'self', null=True, blank=True, related_name='children')
  26. special_role = models.CharField(max_length=255, null=True, blank=True)
  27. role = models.CharField(max_length=255, null=True, blank=True)
  28. name = models.CharField(max_length=255)
  29. slug = models.SlugField(max_length=255)
  30. description = models.TextField(null=True, blank=True)
  31. description_as_html = models.TextField(null=True, blank=True)
  32. is_closed = models.BooleanField(default=False)
  33. redirect_url = models.CharField(max_length=255, null=True, blank=True)
  34. redirects_count = models.PositiveIntegerField(default=0)
  35. threads = models.PositiveIntegerField(default=0)
  36. threads_count = models.PositiveIntegerField(default=0)
  37. posts = models.PositiveIntegerField(default=0)
  38. posts_count = models.PositiveIntegerField(default=0)
  39. prune_started_after = models.PositiveIntegerField(default=0)
  40. prune_replied_after = models.PositiveIntegerField(default=0)
  41. archive_pruned_in = models.ForeignKey('self',
  42. related_name='pruned_archive',
  43. null=True,
  44. blank=True,
  45. on_delete=models.SET_NULL)
  46. css_class = models.CharField(max_length=255, null=True, blank=True)
  47. objects = ForumManager()
  48. def __unicode__(self):
  49. if self.special_role == 'root_category':
  50. return unicode(_('None (will become top level category)'))
  51. elif self.special_role == 'private_threads':
  52. return unicode(_('Private Threads'))
  53. else:
  54. return self.name
  55. def save(self, *args, **kwargs):
  56. if self.pk:
  57. acl_version.invalidate()
  58. return super(Forum, self).save(*args, **kwargs)
  59. def delete(self, *args, **kwargs):
  60. acl_version.invalidate()
  61. return super(Forum, self).delete(*args, **kwargs)
  62. @property
  63. def redirect_host(self):
  64. return urlparse(self.redirect_url).hostname
  65. def set_name(self, name):
  66. self.name = name
  67. self.slug = slugify(name)
  68. def set_description(self, description):
  69. self.description = description
  70. self.description_as_html = subset_markdown(description)
  71. def has_child(self, child):
  72. return child.lft > self.lft and child.rght < self.rght
  73. class ForumRole(BaseRole):
  74. pass
  75. class RoleForumACL(models.Model):
  76. role = models.ForeignKey('misago_acl.Role', related_name='forums_acls')
  77. forum = models.ForeignKey('Forum', related_name='forum_role_set')
  78. forum_role = models.ForeignKey(ForumRole)
  79. """
  80. Signal handlers
  81. """
  82. @receiver(secret_key_changed)
  83. def update_roles_pickles(sender, **kwargs):
  84. for role in ForumRole.objects.iterator():
  85. if role.pickled_permissions:
  86. role.pickled_permissions = serializer.regenerate_checksum(
  87. role.pickled_permissions)
  88. role.save(update_fields=['pickled_permissions'])