threadslist.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. from django.conf import settings
  2. from django.core.urlresolvers import reverse
  3. from django.http import Http404
  4. from django.shortcuts import render
  5. from django.views.generic import View
  6. from django.utils.translation import ugettext_lazy
  7. from misago.acl import add_acl
  8. from misago.categories.models import CATEGORIES_TREE_ID, Category
  9. from misago.categories.permissions import (
  10. allow_see_category, allow_browse_category)
  11. from misago.categories.serializers import (
  12. BasicCategorySerializer, IndexCategorySerializer)
  13. from misago.core.shortcuts import paginate, pagination_dict, validate_slug
  14. from misago.readtracker import threadstracker
  15. from misago.threads.mixins.threadslists import ThreadsListMixin
  16. from misago.threads.serializers import ThreadListSerializer
  17. from misago.threads.subscriptions import make_subscription_aware
  18. from misago.threads.utils import add_categories_to_threads
  19. LISTS_NAMES = {
  20. 'all': None,
  21. 'my': ugettext_lazy("Your threads"),
  22. 'new': ugettext_lazy("New threads"),
  23. 'unread': ugettext_lazy("Unread threads"),
  24. 'subscribed': ugettext_lazy("Subscribed threads"),
  25. 'unapproved': ugettext_lazy("Unapproved content"),
  26. }
  27. class BaseList(View):
  28. template_name = 'misago/threadslist/threads.html'
  29. preloaded_data_prefix = ''
  30. def get_subcategories(self, category, categories):
  31. subcategories = []
  32. for subcategory in categories:
  33. if category.has_child(subcategory):
  34. subcategories.append(subcategory)
  35. return subcategories
  36. def get_pinned_threads(self, request, queryset):
  37. return []
  38. def get_rest_queryset(self, request, queryset, threads_categories):
  39. return queryset.filter(category__in=threads_categories)
  40. def get_extra_context(self, request):
  41. return {}
  42. def set_extra_frontend_context(self, request):
  43. pass
  44. def get(self, request, **kwargs):
  45. try:
  46. page = int(request.GET.get('page', 0))
  47. if page == 1:
  48. page = None
  49. except ValueError:
  50. raise Http404()
  51. list_type = kwargs['list_type']
  52. categories = self.get_categories(request)
  53. category = self.get_category(request, categories, **kwargs)
  54. self.allow_see_list(request, category, list_type)
  55. subcategories = self.get_subcategories(category, categories)
  56. queryset = self.get_queryset(request, categories, list_type)
  57. threads_categories = [category] + subcategories
  58. rest_queryset = self.get_rest_queryset(queryset, threads_categories)
  59. page = paginate(rest_queryset, page, 24, 6)
  60. paginator = pagination_dict(page, include_page_range=False)
  61. if page.number > 1:
  62. threads = list(page.object_list)
  63. else:
  64. pinned_threads = self.get_pinned_threads(
  65. queryset, threads_categories)
  66. threads = list(pinned_threads) + list(page.object_list)
  67. if list_type in ('new', 'unread'):
  68. """we already know all threads on list are unread"""
  69. threadstracker.make_unread(threads)
  70. else:
  71. threadstracker.make_threads_read_aware(
  72. request.user, threads)
  73. add_categories_to_threads(category, categories, threads)
  74. visible_subcategories = []
  75. for thread in threads:
  76. if (thread.top_category and
  77. thread.category in threads_categories and
  78. thread.top_category.pk not in visible_subcategories):
  79. visible_subcategories.append(thread.top_category.pk)
  80. category.subcategories = []
  81. for subcategory in subcategories:
  82. if subcategory.pk in visible_subcategories:
  83. category.subcategories.append(subcategory)
  84. add_acl(request.user, threads)
  85. make_subscription_aware(request.user, threads)
  86. request.frontend_context.update({
  87. 'THREADS': dict(
  88. results=ThreadListSerializer(threads, many=True).data,
  89. subcategories=[c.pk for c in category.subcategories],
  90. **paginator),
  91. 'CATEGORIES': IndexCategorySerializer(categories, many=True).data,
  92. })
  93. if categories[0].special_role:
  94. request.frontend_context['CATEGORIES'][0]['special_role'] = True
  95. self.set_frontend_context(request)
  96. return render(request, self.template_name, dict(
  97. category=category,
  98. list_type=list_type,
  99. list_name=LISTS_NAMES[list_type],
  100. threads=threads,
  101. paginator=paginator,
  102. count=paginator['count'],
  103. **self.get_extra_context(request)
  104. ))
  105. class ThreadsList(BaseList, ThreadsListMixin):
  106. template_name = 'misago/threadslist/threads.html'
  107. def get_category(self, request, categories, **kwargs):
  108. return categories[0]
  109. def get_pinned_threads(self, queryset, threads_categories):
  110. return queryset.filter(weight=2)
  111. def get_rest_queryset(self, queryset, threads_categories):
  112. return queryset.filter(
  113. weight__lt=2,
  114. category__in=threads_categories,
  115. )
  116. def get_extra_context(self, request):
  117. return {
  118. 'is_index': not settings.MISAGO_CATEGORIES_ON_INDEX
  119. }
  120. def set_frontend_context(self, request):
  121. request.frontend_context.update({
  122. 'THREADS_API': reverse('misago:api:thread-list'),
  123. })
  124. class CategoryThreadsList(ThreadsList, ThreadsListMixin):
  125. template_name = 'misago/threadslist/category.html'
  126. preloaded_data_prefix = 'CATEGORY_'
  127. def get_category(self, request, categories, **kwargs):
  128. for category in categories:
  129. if category.pk == int(kwargs['pk']):
  130. if not category.level:
  131. raise Http404()
  132. allow_see_category(request.user, category)
  133. allow_browse_category(request.user, category)
  134. validate_slug(category, kwargs['slug'])
  135. return category
  136. else:
  137. raise Http404()
  138. def get_pinned_threads(self, queryset, threads_categories):
  139. return list(queryset.filter(weight=2)) + list(queryset.filter(
  140. weight=1,
  141. category__in=threads_categories
  142. ))
  143. def get_rest_queryset(self, queryset, threads_categories):
  144. return queryset.filter(
  145. weight=0,
  146. category__in=threads_categories,
  147. )
  148. class PrivateThreadsList(ThreadsList):
  149. template_name = 'misago/threadslist/private_threads.html'
  150. preloaded_data_prefix = 'PRIVATE_'
  151. def get_category(self, request, **kwargs):
  152. return Category.objects.private_threads()
  153. def get_subcategories(self, request, category):
  154. return []