forum.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. from django.core.urlresolvers import reverse
  2. from django.db.models import Q
  3. from django.shortcuts import redirect
  4. from django.utils.translation import ugettext_lazy, ugettext as _
  5. from misago.core.shortcuts import paginate
  6. from misago.forums.lists import get_forums_list, get_forum_path
  7. from misago.threads.posting import (PostingInterrupt, EditorFormset,
  8. START, REPLY, EDIT)
  9. from misago.threads.models import ANNOUNCEMENT, Thread
  10. from misago.threads.views.generic.threads import OrderThreadsMixin, ThreadsView
  11. __all__ = ['FilterThreadsMixin', 'ForumView']
  12. class FilterThreadsMixin(object):
  13. def get_filter_name(self, filters, filter_by):
  14. if filters:
  15. if filter_by:
  16. for filtering in filters:
  17. if filtering[0] == filter_by:
  18. return filtering[1]
  19. else:
  20. return _("All threads")
  21. else:
  22. return None
  23. def get_filters_dicts(self, filters, exclude_filter, links_params):
  24. url_kwargs = links_params.copy()
  25. dicts = []
  26. if filters and exclude_filter:
  27. url_kwargs.pop('show', None)
  28. dicts.append({
  29. 'url': reverse(self.link_name, kwargs=url_kwargs),
  30. 'name': _("All threads"),
  31. })
  32. for filtering in filters:
  33. if filtering[0] != exclude_filter:
  34. url_kwargs['show'] = filtering[0]
  35. dicts.append({
  36. 'url': reverse(self.link_name, kwargs=url_kwargs),
  37. 'name': filtering[1],
  38. })
  39. return dicts
  40. class ForumView(FilterThreadsMixin, OrderThreadsMixin, ThreadsView):
  41. """
  42. Basic view for threads lists
  43. """
  44. template = 'misago/threads/forum.html'
  45. def get_threads(self, request, forum, kwargs,
  46. order_by=None, filter_by=None):
  47. org_queryset = self.get_threads_queryset(request, forum)
  48. queryset = self.filter_all_querysets(request, forum, org_queryset)
  49. queryset = self.set_custom_filter(request, queryset, filter_by)
  50. announcements_qs = queryset.filter(weight=ANNOUNCEMENT)
  51. threads_qs = queryset.filter(weight__lt=ANNOUNCEMENT)
  52. threads_qs = self.filter_threads_queryset(request, forum, threads_qs)
  53. threads_qs, announcements_qs = self.order_querysets(
  54. order_by, threads_qs, announcements_qs)
  55. page = paginate(threads_qs, kwargs.get('page', 0), 20, 10)
  56. threads = []
  57. for announcement in announcements_qs:
  58. threads.append(announcement)
  59. for thread in page.object_list:
  60. threads.append(thread)
  61. for thread in threads:
  62. thread.forum = forum
  63. return page, threads
  64. def order_querysets(self, order_by, threads, announcements):
  65. if order_by == 'recently-replied':
  66. threads = threads.order_by('-weight', '-last_post')
  67. announcements = announcements.order_by('-last_post')
  68. if order_by == 'last-replied':
  69. threads = threads.order_by('weight', 'last_post')
  70. announcements = announcements.order_by('last_post')
  71. if order_by == 'most-replied':
  72. threads = threads.order_by('-weight', '-replies')
  73. announcements = announcements.order_by('-replies')
  74. if order_by == 'least-replied':
  75. threads = threads.order_by('weight', 'replies')
  76. announcements = announcements.order_by('replies')
  77. if order_by == 'newest':
  78. threads = threads.order_by('-weight', '-id')
  79. announcements = announcements.order_by('-id')
  80. if order_by == 'oldest':
  81. threads = threads.order_by('weight', 'id')
  82. announcements = announcements.order_by('id')
  83. return threads, announcements
  84. def filter_all_querysets(self, request, forum, queryset):
  85. if request.user.is_authenticated():
  86. condition_author = Q(starter_id=request.user.id)
  87. can_mod = forum.acl['can_review_moderated_content']
  88. can_hide = forum.acl['can_hide_threads']
  89. if not can_mod and not can_hide:
  90. condition = Q(is_moderated=False) & Q(is_hidden=False)
  91. queryset = queryset.filter(condition_author | condition)
  92. elif not can_mod:
  93. condition = Q(is_moderated=False)
  94. queryset = queryset.filter(condition_author | condition)
  95. elif not can_hide:
  96. condition = Q(is_hidden=False)
  97. queryset = queryset.filter(condition_author | condition)
  98. else:
  99. if not forum.acl['can_review_moderated_content']:
  100. queryset = queryset.filter(is_moderated=False)
  101. if not forum.acl['can_hide_threads']:
  102. queryset = queryset.filter(is_hidden=False)
  103. return queryset
  104. def filter_threads_queryset(self, request, forum, queryset):
  105. if forum.acl['can_see_own_threads']:
  106. if request.user.is_authenticated():
  107. queryset = queryset.filter(starter_id=request.user.id)
  108. else:
  109. queryset = queryset.filter(starter_id=0)
  110. return queryset
  111. def set_custom_filter(self, request, queryset, filter_by):
  112. if filter_by == 'my-threads':
  113. return queryset.filter(starter_id=request.user.id)
  114. elif filter_by == 'reported':
  115. return queryset.filter(has_reported_posts=True)
  116. elif filter_by == 'moderated-threads':
  117. return queryset.filter(is_moderated=True)
  118. elif filter_by == 'moderated-posts':
  119. return queryset.filter(has_moderated_posts=True)
  120. else:
  121. return queryset
  122. def get_threads_queryset(self, request, forum):
  123. return forum.thread_set.all().order_by('-last_post_id')
  124. def get_default_link_params(self, forum):
  125. message = "forum views have to define get_default_link_params"
  126. raise NotImplementedError(message)
  127. def get_available_filters(self, request, forum):
  128. filters = []
  129. if request.user.is_authenticated():
  130. if forum.acl['can_see_all_threads']:
  131. filters.append(('my-threads', _("My threads")))
  132. if forum.acl['can_see_reports']:
  133. filters.append(('reported', _("With reported posts")))
  134. if forum.acl['can_review_moderated_content']:
  135. filters.extend((
  136. ('moderated-threads', _("Moderated threads")),
  137. ('moderated-posts', _("With moderated posts")),
  138. ))
  139. return filters
  140. def dispatch(self, request, *args, **kwargs):
  141. forum = self.get_forum(request, **kwargs)
  142. links_params = self.get_default_link_params(forum)
  143. if forum.lft + 1 < forum.rght:
  144. forum.subforums = get_forums_list(request.user, forum)
  145. else:
  146. forum.subforums = []
  147. if request.user.is_anonymous():
  148. if kwargs.get('sort') or kwargs.get('show'):
  149. """we don't allow sort/filter for guests"""
  150. kwargs.pop('sort', None)
  151. kwargs.pop('show', None)
  152. return redirect('misago:forum', **kwargs)
  153. order_by = self.get_ordering(kwargs)
  154. if self.is_ordering_default(kwargs.get('sort')):
  155. kwargs.pop('sort')
  156. return redirect('misago:forum', **kwargs)
  157. elif not self.is_ordering_default(order_by):
  158. links_params['sort'] = order_by
  159. available_filters = self.get_available_filters(request, forum)
  160. if available_filters and kwargs.get('show'):
  161. filter_methods = [f[0] for f in available_filters]
  162. if kwargs.get('show') not in filter_methods:
  163. kwargs.pop('show')
  164. return redirect('misago:forum', **kwargs)
  165. else:
  166. filter_by = kwargs.get('show')
  167. links_params['show'] = filter_by
  168. else:
  169. filter_by = None
  170. page, threads = self.get_threads(
  171. request, forum, kwargs, order_by, filter_by)
  172. self.add_threads_reads(request, threads)
  173. return self.render(request, {
  174. 'forum': forum,
  175. 'path': get_forum_path(forum),
  176. 'page': page,
  177. 'paginator': page.paginator,
  178. 'threads': threads,
  179. 'link_name': self.link_name,
  180. 'links_params': links_params,
  181. 'is_filtering': bool(filter_by),
  182. 'filter_name': self.get_filter_name(available_filters, filter_by),
  183. 'filters': self.get_filters_dicts(
  184. available_filters, filter_by, links_params),
  185. 'order_name': self.get_ordering_name(order_by),
  186. 'order_by': self.get_orderings_dicts(order_by, links_params),
  187. })