list.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. from django.core.urlresolvers import reverse
  2. from django.db.models import Q
  3. from django.shortcuts import redirect
  4. from django.template import RequestContext
  5. from django.utils.translation import ugettext as _
  6. from misago.acl.utils import ACLError403, ACLError404
  7. from misago.forms import FormLayout, FormFields
  8. from misago.forums.models import Forum
  9. from misago.messages import Message
  10. from misago.readstracker.trackers import ForumsTracker, ThreadsTracker
  11. from misago.threads.models import Thread, Post
  12. from misago.threads.views.base import BaseView
  13. from misago.threads.views.mixins import ThreadsFormMixin
  14. from misago.views import error403, error404
  15. from misago.utils import make_pagination
  16. class ThreadsView(BaseView, ThreadsFormMixin):
  17. def fetch_forum(self, forum):
  18. self.forum = Forum.objects.get(pk=forum, type='forum')
  19. self.request.acl.forums.allow_forum_view(self.forum)
  20. self.parents = self.forum.get_ancestors().filter(level__gt=1)
  21. if self.forum.lft + 1 != self.forum.rght:
  22. self.forum.subforums = Forum.objects.treelist(self.request.acl.forums, self.forum, tracker=ForumsTracker(self.request.user))
  23. self.tracker = ThreadsTracker(self.request.user, self.forum)
  24. def fetch_threads(self, page):
  25. self.count = self.request.acl.threads.filter_threads(self.request, self.forum, Thread.objects.filter(forum=self.forum).filter(weight__lt=2)).count()
  26. self.pagination = make_pagination(page, self.count, self.request.settings.threads_per_page)
  27. self.threads = []
  28. for thread in Thread.objects.filter(Q(forum=self.request.monitor['anno']) | (Q(forum=self.forum) & Q(weight=2))):
  29. self.threads.append(thread)
  30. for thread in self.request.acl.threads.filter_threads(self.request, self.forum, Thread.objects.filter(forum=self.forum).filter(weight__lt=2)).order_by('-weight', '-last'):
  31. self.threads.append(thread)
  32. if self.request.settings.threads_per_page < self.count:
  33. self.threads = self.threads[self.pagination['start']:self.pagination['stop']]
  34. for thread in self.threads:
  35. thread.is_read = self.tracker.is_read(thread)
  36. def get_thread_actions(self):
  37. acl = self.request.acl.threads.get_role(self.forum)
  38. actions = []
  39. try:
  40. if acl['can_approve']:
  41. actions.append(('accept', _('Accept threads')))
  42. if acl['can_pin_threads'] == 2:
  43. actions.append(('annouce', _('Change to annoucements')))
  44. if acl['can_pin_threads'] > 0:
  45. actions.append(('sticky', _('Change to sticky threads')))
  46. if acl['can_pin_threads'] > 0:
  47. actions.append(('normal', _('Change to standard thread')))
  48. if acl['can_move_threads_posts']:
  49. actions.append(('move', _('Move threads')))
  50. actions.append(('merge', _('Merge threads')))
  51. if acl['can_close_threads']:
  52. actions.append(('open', _('Open threads')))
  53. actions.append(('close', _('Close threads')))
  54. if acl['can_delete_threads']:
  55. actions.append(('undelete', _('Undelete threads')))
  56. if acl['can_delete_threads']:
  57. actions.append(('soft', _('Soft delete threads')))
  58. if acl['can_delete_threads'] == 2:
  59. actions.append(('hard', _('Hard delete threads')))
  60. except KeyError:
  61. pass
  62. return actions
  63. def action_accept(self, ids):
  64. accepted = 0
  65. posts = 0
  66. users = []
  67. for thread in self.threads:
  68. if thread.pk in ids and thread.moderated:
  69. accepted += 1
  70. # Sync thread and post
  71. thread.moderated = False
  72. thread.replies_moderated -= 1
  73. thread.save(force_update=True)
  74. thread.start_post.moderated = False
  75. thread.start_post.save(force_update=True)
  76. # Sync user
  77. if thread.last_post.user:
  78. thread.start_post.user.threads += 1
  79. thread.start_post.user.posts += 1
  80. users.append(thread.start_post.user)
  81. thread.last_post.set_checkpoint(self.request, 'accepted')
  82. # Sync forum
  83. self.forum.threads += 1
  84. self.forum.threads_delta += 1
  85. self.forum.posts += thread.replies + 1
  86. posts += thread.replies + 1
  87. self.forum.posts_delta += thread.replies + 1
  88. if not self.forum.last_thread_date or self.forum.last_thread_date < thread.last:
  89. self.forum.last_thread = thread
  90. self.forum.last_thread_name = thread.name
  91. self.forum.last_thread_slug = thread.slug
  92. self.forum.last_thread_date = thread.last
  93. self.forum.last_poster = thread.last_poster
  94. self.forum.last_poster_name = thread.last_poster_name
  95. self.forum.last_poster_slug = thread.last_poster_slug
  96. self.forum.last_poster_style = thread.last_poster_style
  97. if accepted:
  98. self.request.monitor['threads'] = int(self.request.monitor['threads']) + accepted
  99. self.request.monitor['posts'] = posts
  100. self.forum.save(force_update=True)
  101. for user in users:
  102. user.save(force_update=True)
  103. self.request.messages.set_flash(Message(_('Selected threads have been marked as reviewed and made visible to other members.')), 'success', 'threads')
  104. def action_annouce(self, ids):
  105. acl = self.request.acl.threads.get_role(self.forum)
  106. annouced = []
  107. for thread in self.threads:
  108. if thread.pk in ids and thread.weight < 2:
  109. annouced.append(thread.pk)
  110. if annouced:
  111. Thread.objects.filter(id__in=annouced).update(weight=2)
  112. self.request.messages.set_flash(Message(_('Selected threads have been turned into annoucements.')), 'success', 'threads')
  113. def action_sticky(self, ids):
  114. sticky = []
  115. for thread in self.threads:
  116. if thread.pk in ids and thread.weight != 1 and (acl['can_pin_threads'] == 2 or thread.weight < 2):
  117. sticky.append(thread.pk)
  118. if sticky:
  119. Thread.objects.filter(id__in=sticky).update(weight=1)
  120. self.request.messages.set_flash(Message(_('Selected threads have been sticked to the top of list.')), 'success', 'threads')
  121. def action_normal(self, ids):
  122. normalised = []
  123. for thread in self.threads:
  124. if thread.pk in ids and thread.weight > 0:
  125. normalised.append(thread.pk)
  126. if normalised:
  127. Thread.objects.filter(id__in=normalised).update(weight=0)
  128. self.request.messages.set_flash(Message(_('Selected threads weight has been removed.')), 'success', 'threads')
  129. def action_open(self, ids):
  130. opened = []
  131. for thread in self.threads:
  132. if thread.pk in ids and thread.closed:
  133. opened.append(thread.pk)
  134. thread.last_post.set_checkpoint(self.request, 'opened')
  135. if opened:
  136. Thread.objects.filter(id__in=opened).update(closed=False)
  137. self.request.messages.set_flash(Message(_('Selected threads have been opened.')), 'success', 'threads')
  138. def action_close(self, ids):
  139. closed = []
  140. for thread in self.threads:
  141. if thread.pk in ids and not thread.closed:
  142. closed.append(thread.pk)
  143. thread.last_post.set_checkpoint(self.request, 'closed')
  144. if closed:
  145. Thread.objects.filter(id__in=closed).update(closed=True)
  146. self.request.messages.set_flash(Message(_('Selected threads have been closed.')), 'success', 'threads')
  147. def action_undelete(self, ids):
  148. undeleted = []
  149. posts = 0
  150. for thread in self.threads:
  151. if thread.pk in ids and thread.deleted:
  152. undeleted.append(thread.pk)
  153. posts += thread.replies + 1
  154. thread.start_post.deleted = False
  155. thread.start_post.save(force_update=True)
  156. thread.last_post.set_checkpoint(self.request, 'undeleted')
  157. if undeleted:
  158. self.request.monitor['threads'] = int(self.request.monitor['threads']) + len(undeleted)
  159. self.request.monitor['posts'] = int(self.request.monitor['posts']) + posts
  160. self.forum.threads += len(undeleted)
  161. self.forum.posts += posts
  162. self.forum.save(force_update=True)
  163. Thread.objects.filter(id__in=undeleted).update(deleted=False)
  164. self.request.messages.set_flash(Message(_('Selected threads have been undeleted.')), 'success', 'threads')
  165. def action_soft(self, ids):
  166. deleted = []
  167. posts = 0
  168. for thread in self.threads:
  169. if thread.pk in ids and not thread.deleted:
  170. deleted.append(thread.pk)
  171. posts += thread.replies + 1
  172. thread.start_post.deleted = True
  173. thread.start_post.save(force_update=True)
  174. thread.last_post.set_checkpoint(self.request, 'deleted')
  175. if deleted:
  176. self.request.monitor['threads'] = int(self.request.monitor['threads']) - len(deleted)
  177. self.request.monitor['posts'] = int(self.request.monitor['posts']) - posts
  178. self.forum.sync()
  179. self.forum.save(force_update=True)
  180. Thread.objects.filter(id__in=deleted).update(deleted=True)
  181. self.request.messages.set_flash(Message(_('Selected threads have been softly deleted.')), 'success', 'threads')
  182. def action_hard(self, ids):
  183. deleted = []
  184. posts = 0
  185. for thread in self.threads:
  186. if thread.pk in ids:
  187. deleted.append(thread.pk)
  188. posts += thread.replies + 1
  189. thread.delete()
  190. if deleted:
  191. self.request.monitor['threads'] = int(self.request.monitor['threads']) - len(deleted)
  192. self.request.monitor['posts'] = int(self.request.monitor['posts']) - posts
  193. self.forum.sync()
  194. self.forum.save(force_update=True)
  195. self.request.messages.set_flash(Message(_('Selected threads have been deleted.')), 'success', 'threads')
  196. def __call__(self, request, slug=None, forum=None, page=0):
  197. self.request = request
  198. self.pagination = None
  199. self.parents = None
  200. self.message = request.messages.get_message('threads')
  201. try:
  202. self.fetch_forum(forum)
  203. self.fetch_threads(page)
  204. self.make_form()
  205. if self.form:
  206. response = self.handle_form()
  207. if response:
  208. return response
  209. except Forum.DoesNotExist:
  210. return error404(request)
  211. except ACLError403 as e:
  212. return error403(request, e.message)
  213. except ACLError404 as e:
  214. return error404(request, e.message)
  215. return request.theme.render_to_response('threads/list.html',
  216. {
  217. 'message': self.message,
  218. 'forum': self.forum,
  219. 'parents': self.parents,
  220. 'count': self.count,
  221. 'list_form': FormFields(self.form).fields if self.form else None,
  222. 'threads': self.threads,
  223. 'pagination': self.pagination,
  224. },
  225. context_instance=RequestContext(request));