list.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. from itertools import chain
  2. from django.core.urlresolvers import reverse
  3. from django.http import Http404
  4. from django.shortcuts import redirect
  5. from django.utils.translation import ugettext as _
  6. from misago import messages
  7. from misago.acl.exceptions import ACLError403, ACLError404
  8. from misago.apps.errors import error403, error404
  9. from misago.apps.threadtype.list import ThreadsListBaseView, ThreadsListModeration
  10. from misago.conf import settings
  11. from misago.decorators import check_csrf
  12. from misago.models import Forum, Thread, ThreadPrefix
  13. from misago.readstrackers import ThreadsTracker
  14. from misago.utils.pagination import make_pagination
  15. from misago.apps.threads.mixins import TypeMixin
  16. class ThreadsListView(ThreadsListBaseView, ThreadsListModeration, TypeMixin):
  17. def fetch_forum(self):
  18. self.forum = Forum.objects.get(pk=self.kwargs.get('forum'), type='forum')
  19. self.prefixes = ThreadPrefix.objects.forum_prefixes(self.forum)
  20. self.active_prefix = self.request.session.get('forum_prefix_%s' % self.forum.pk)
  21. if self.active_prefix and self.active_prefix.pk not in self.prefixes:
  22. self.active_prefix = None
  23. def template_vars(self, context):
  24. context['prefixes'] = self.prefixes
  25. context['active_prefix'] = self.active_prefix
  26. return context
  27. def threads_queryset(self):
  28. announcements = self.request.acl.threads.filter_threads(self.request, self.forum, self.forum.thread_set).filter(weight=2).order_by('-pk')
  29. threads = self.request.acl.threads.filter_threads(self.request, self.forum, self.forum.thread_set).filter(weight__lt=2).order_by('-weight', '-last')
  30. if self.active_prefix:
  31. threads = threads.filter(prefix=self.active_prefix)
  32. # Dont display threads by ignored users (unless they are important)
  33. if self.request.user.is_authenticated():
  34. ignored_users = self.request.user.ignored_users()
  35. if ignored_users:
  36. threads = threads.exclude(start_poster_id__in=ignored_users)
  37. # Add in first and last poster
  38. if settings.avatars_on_threads_list:
  39. announcements = announcements.prefetch_related('start_poster', 'last_poster')
  40. threads = threads.prefetch_related('start_poster', 'last_poster')
  41. return announcements, threads
  42. def fetch_threads(self):
  43. qs_announcements, qs_threads = self.threads_queryset()
  44. self.count = qs_threads.count()
  45. try:
  46. self.pagination = make_pagination(self.kwargs.get('page', 0), self.count, settings.threads_per_page)
  47. except Http404:
  48. return self.threads_list_redirect()
  49. tracker_forum = ThreadsTracker(self.request, self.forum)
  50. for thread in list(chain(qs_announcements, qs_threads[self.pagination['start']:self.pagination['stop']])):
  51. thread.is_read = tracker_forum.is_read(thread)
  52. self.threads.append(thread)
  53. def threads_actions(self):
  54. acl = self.request.acl.threads.get_role(self.forum)
  55. actions = []
  56. try:
  57. if acl['can_approve']:
  58. actions.append(('accept', _('Accept threads')))
  59. if acl['can_change_prefixes']:
  60. actions.append(('prefix:0', _('Remove prefix')))
  61. for prefix in self.prefixes.values():
  62. actions.append(('prefix:%s' % prefix.pk, _('Change prefix to: %(prefix)s') % {'prefix': _(prefix.name)}))
  63. if acl['can_pin_threads'] == 2:
  64. actions.append(('annouce', _('Change to announcements')))
  65. if acl['can_pin_threads'] > 0:
  66. actions.append(('sticky', _('Change to sticky threads')))
  67. if acl['can_pin_threads'] > 0:
  68. actions.append(('normal', _('Change to standard thread')))
  69. if acl['can_move_threads_posts']:
  70. actions.append(('move', _('Move threads')))
  71. actions.append(('merge', _('Merge threads')))
  72. if acl['can_close_threads']:
  73. actions.append(('open', _('Open threads')))
  74. actions.append(('close', _('Close threads')))
  75. if acl['can_delete_threads']:
  76. actions.append(('undelete', _('Restore threads')))
  77. actions.append(('soft', _('Hide threads')))
  78. if acl['can_delete_threads'] == 2:
  79. actions.append(('hard', _('Delete threads')))
  80. except KeyError:
  81. pass
  82. return actions
  83. def action_prefix(self, ids, prefix):
  84. prefixes = self.prefixes
  85. try:
  86. prefix = int(prefix)
  87. except TypeError:
  88. prefix = 0
  89. prefix = prefix or None
  90. if prefix:
  91. if self._action_set_prefix(ids, prefixes[prefix]):
  92. messages.success(self.request, _('Selected threads prefix has been changed to "%(name)s".') % {'name': _(prefixes[prefix].name)}, 'threads')
  93. else:
  94. messages.info(self.request, _('No threads prefix was changed.'), 'threads')
  95. else:
  96. if self._action_remove_prefix(ids):
  97. messages.success(self.request, _('Selected threads prefix has been removed.'), 'threads')
  98. else:
  99. messages.info(self.request, _('No threads prefixes were removed.'), 'threads')
  100. def _action_set_prefix(self, ids, prefix):
  101. changed = []
  102. for thread in self.threads:
  103. if thread.pk in ids and prefix.pk != thread.prefix_id:
  104. changed.append(thread.pk)
  105. thread.prefix = prefix
  106. thread.set_checkpoint(self.request, 'changed_prefix', self.request.user, self.forum, extra=prefix.name)
  107. thread.save(force_update=True)
  108. return changed
  109. def _action_remove_prefix(self, ids):
  110. changed = []
  111. for thread in self.threads:
  112. if thread.pk in ids and not thread.prefix_id:
  113. changed.append(thread.pk)
  114. thread.prefix_id = None
  115. thread.set_checkpoint(self.request, 'removed_prefix', self.request.user, self.forum)
  116. thread.save(force_update=True)
  117. return changed
  118. class ForumSwitchThreadPrefix(ThreadsListView):
  119. def __call__(self, request, **kwargs):
  120. self.request = request
  121. self.kwargs = kwargs
  122. self.pagination = {}
  123. self.parents = []
  124. self.threads = []
  125. self.message = request.messages.get_message('threads')
  126. try:
  127. self._type_available()
  128. self._fetch_forum()
  129. return self.change_prefix()
  130. except (Forum.DoesNotExist, Thread.DoesNotExist):
  131. return error404(request)
  132. except ACLError403 as e:
  133. return error403(request, unicode(e))
  134. except ACLError404 as e:
  135. return error404(request, unicode(e))
  136. def change_prefix(self):
  137. @check_csrf
  138. def view(request):
  139. session_key = 'forum_prefix_%s' % self.forum.pk
  140. try:
  141. new_prefix = int(self.request.POST.get('switch_prefix', 0))
  142. except ValueError:
  143. new_prefix = 0
  144. if self.prefixes and new_prefix in self.prefixes:
  145. self.request.session[session_key] = self.prefixes[new_prefix]
  146. messages.info(self.request, _('Displaying only threads that are prefixed with "%(prefix)s".') % {'prefix': _(self.prefixes[new_prefix].name)}, 'threads')
  147. else:
  148. self.request.session[session_key] = None
  149. messages.info(self.request, _("Displaying all threads."), 'threads')
  150. if 'retreat' in self.request.POST:
  151. return redirect(self.request.POST.get('retreat'))
  152. return self.threads_list_redirect()
  153. return view(self.request)