models.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. from django.conf import settings
  2. from django.db import models
  3. from django.utils.translation import ugettext_lazy as _
  4. from mptt.models import MPTTModel,TreeForeignKey
  5. from misago.roles.models import Role
  6. class ForumManager(models.Manager):
  7. def treelist(self, acl, parent=None, tracker=None):
  8. complete_list = []
  9. forums_list = []
  10. parents = {}
  11. if parent:
  12. queryset = Forum.objects.filter(pk__in=acl.known_forums).filter(lft__gt=parent.lft).filter(rght__lt=parent.rght).order_by('lft')
  13. else:
  14. queryset = Forum.objects.filter(pk__in=acl.known_forums).order_by('lft')
  15. for forum in queryset:
  16. forum.subforums = []
  17. forum.is_read = False
  18. if tracker:
  19. forum.is_read = tracker.is_read(forum)
  20. parents[forum.pk] = forum
  21. complete_list.append(forum)
  22. if forum.parent_id in parents:
  23. parents[forum.parent_id].subforums.append(forum)
  24. else:
  25. forums_list.append(forum)
  26. # Second iteration - sum up forum counters
  27. for forum in reversed(complete_list):
  28. if forum.parent_id in parents and parents[forum.parent_id].type != 'redirect':
  29. parents[forum.parent_id].threads += forum.threads
  30. parents[forum.parent_id].threads_delta += forum.threads_delta
  31. parents[forum.parent_id].posts += forum.posts
  32. parents[forum.parent_id].posts_delta += forum.posts_delta
  33. if acl.can_browse(forum.pk):
  34. # If forum is unread, make parent unread too
  35. if not forum.is_read:
  36. parents[forum.parent_id].is_read = False
  37. # Sum stats
  38. if forum.last_thread_date and (not parents[forum.parent_id].last_thread_date or forum.last_thread_date > parents[forum.parent_id].last_thread_date):
  39. parents[forum.parent_id].last_thread_id = forum.last_thread_id
  40. parents[forum.parent_id].last_thread_name = forum.last_thread_name
  41. parents[forum.parent_id].last_thread_slug = forum.last_thread_slug
  42. parents[forum.parent_id].last_thread_date = forum.last_thread_date
  43. parents[forum.parent_id].last_poster_id = forum.last_poster_id
  44. parents[forum.parent_id].last_poster_name = forum.last_poster_name
  45. parents[forum.parent_id].last_poster_slug = forum.last_poster_slug
  46. parents[forum.parent_id].last_poster_style = forum.last_poster_style
  47. return forums_list
  48. class Forum(MPTTModel):
  49. parent = TreeForeignKey('self',null=True,blank=True,related_name='children')
  50. type = models.CharField(max_length=12)
  51. token = models.CharField(max_length=255,null=True,blank=True)
  52. name = models.CharField(max_length=255)
  53. slug = models.SlugField(max_length=255)
  54. description = models.TextField(null=True,blank=True)
  55. description_preparsed = models.TextField(null=True,blank=True)
  56. threads = models.PositiveIntegerField(default=0)
  57. threads_delta = models.PositiveIntegerField(default=0)
  58. posts = models.PositiveIntegerField(default=0)
  59. posts_delta = models.IntegerField(default=0)
  60. redirects = models.PositiveIntegerField(default=0)
  61. redirects_delta = models.IntegerField(default=0)
  62. last_thread = models.ForeignKey('threads.Thread',related_name='+',null=True,blank=True,on_delete=models.SET_NULL)
  63. last_thread_name = models.CharField(max_length=255,null=True,blank=True)
  64. last_thread_slug = models.SlugField(null=True,blank=True)
  65. last_thread_date = models.DateTimeField(null=True,blank=True)
  66. last_poster = models.ForeignKey('users.User',related_name='+',null=True,blank=True,on_delete=models.SET_NULL)
  67. last_poster_name = models.CharField(max_length=255,null=True,blank=True)
  68. last_poster_slug = models.SlugField(max_length=255,null=True,blank=True)
  69. last_poster_style = models.CharField(max_length=255,null=True,blank=True)
  70. prune_start = models.PositiveIntegerField(default=0)
  71. prune_last = models.PositiveIntegerField(default=0)
  72. redirect = models.CharField(max_length=255,null=True,blank=True)
  73. template = models.CharField(max_length=255,null=True,blank=True)
  74. style = models.CharField(max_length=255,null=True,blank=True)
  75. closed = models.BooleanField(default=False)
  76. objects = ForumManager()
  77. def __unicode__(self):
  78. if self.token == 'root':
  79. return unicode(_('Root Category'))
  80. return unicode(self.name)
  81. def set_description(self, description):
  82. self.description = description.strip()
  83. self.description_preparsed = ''
  84. if self.description:
  85. import markdown
  86. self.description_preparsed = markdown.markdown(description,safe_mode='escape',output_format=settings.OUTPUT_FORMAT)
  87. def copy_permissions(self, target):
  88. if target.pk != self.pk:
  89. for role in Role.objects.all():
  90. perms = role.get_permissions()
  91. try:
  92. perms['forums'][self.pk] = perms['forums'][target.pk]
  93. role.set_permissions(perms)
  94. role.save(force_update=True)
  95. except KeyError:
  96. pass
  97. def move_content(self, target):
  98. pass
  99. def sync(self):
  100. self.threads = self.thread_set.filter(moderated=0).filter(deleted=0).count()
  101. self.posts = self.post_set.filter(moderated=0).filter(deleted=0).count()
  102. self.last_poster = None
  103. self.last_poster_name = None
  104. self.last_poster_slug = None
  105. self.last_poster_style = None
  106. self.last_thread = None
  107. self.last_thread_date = None
  108. self.last_thread_name = None
  109. self.last_thread_slug = None
  110. try:
  111. last_thread = self.thread_set.filter(moderated=0).filter(deleted=0).order_by('-last').all()[1:][0]
  112. self.last_poster_name = last_thread.last_poster_name
  113. self.last_poster_slug = last_thread.last_poster_slug
  114. self.last_poster_style = last_thread.last_poster_style
  115. if last_thread.last_poster:
  116. self.last_poster = last_thread.last_poster
  117. self.last_thread = last_thread
  118. self.last_thread_date = last_thread.start
  119. self.last_thread_name = last_thread.name
  120. self.last_thread_slug = last_thread.slug
  121. except (IndexError, AttributeError):
  122. pass
  123. def prune(self):
  124. pass