threadslist.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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.serializers import ThreadListSerializer
  16. from misago.threads.mixins.threadslists import ThreadsListMixin
  17. from misago.threads.utils import add_categories_to_threads
  18. LISTS_NAMES = {
  19. 'my': ugettext_lazy("Your threads"),
  20. 'new': ugettext_lazy("New threads"),
  21. 'unread': ugettext_lazy("Unread threads"),
  22. 'subscribed': ugettext_lazy("Subscribed threads"),
  23. }
  24. class BaseList(View):
  25. template_name = 'misago/threadslist/threads.html'
  26. preloaded_data_prefix = ''
  27. def get_subcategories(self, category, categories):
  28. subcategories = []
  29. for subcategory in categories:
  30. if category.has_child(subcategory):
  31. subcategories.append(subcategory)
  32. return subcategories
  33. def get_extra_context(self, request):
  34. return {}
  35. def set_extra_frontend_context(self, request):
  36. pass
  37. def get(self, request, **kwargs):
  38. try:
  39. page = int(request.GET.get('page', 0))
  40. if page == 1:
  41. page = None
  42. except ValueError:
  43. raise Http404()
  44. list_type = kwargs['list_type']
  45. categories = self.get_categories(request)
  46. category = self.get_category(request, categories, **kwargs)
  47. self.allow_see_list(request, category, list_type)
  48. subcategories = self.get_subcategories(category, categories)
  49. threads_categories = [category] + subcategories
  50. queryset = self.get_queryset(
  51. request, threads_categories, list_type
  52. ).order_by('-last_post_on')
  53. page = paginate(queryset, page, 24, 6)
  54. paginator = pagination_dict(page, include_page_range=False)
  55. if list_type in ('new', 'unread'):
  56. """we already know all threads on list are unread"""
  57. threadstracker.make_unread(page.object_list)
  58. else:
  59. threadstracker.make_threads_read_aware(
  60. request.user, page.object_list)
  61. add_categories_to_threads(threads_categories, page.object_list)
  62. visible_subcategories = []
  63. for thread in page.object_list:
  64. if (thread.top_category and
  65. thread.top_category not in visible_subcategories):
  66. visible_subcategories.append(thread.top_category.pk)
  67. category.subcategories = []
  68. for subcategory in subcategories:
  69. if subcategory.pk in visible_subcategories:
  70. category.subcategories.append(subcategory)
  71. extra_context = self.get_extra_context(request)
  72. show_toolbar = False
  73. if paginator['count']:
  74. if category.subcategories:
  75. show_toolbar = True
  76. if request.user.is_authenticated():
  77. show_toolbar = True
  78. add_acl(request.user, page.object_list)
  79. request.frontend_context.update({
  80. 'THREADS': dict(
  81. results=ThreadListSerializer(page.object_list, many=True).data,
  82. subcategories=[c.pk for c in category.subcategories],
  83. **paginator),
  84. 'CATEGORIES': IndexCategorySerializer(categories, many=True).data,
  85. })
  86. if categories[0].special_role:
  87. request.frontend_context['CATEGORIES'][0]['special_role'] = True
  88. self.set_frontend_context(request)
  89. return render(request, self.template_name, dict(
  90. category=category,
  91. show_toolbar=show_toolbar,
  92. list_type=list_type,
  93. list_name=LISTS_NAMES.get(list_type),
  94. threads=page.object_list,
  95. paginator=paginator,
  96. count=paginator['count'],
  97. **extra_context
  98. ))
  99. class ThreadsList(BaseList, ThreadsListMixin):
  100. template_name = 'misago/threadslist/threads.html'
  101. def get_categories(self, request):
  102. return [Category.objects.root_category()] + list(
  103. Category.objects.all_categories().filter(
  104. id__in=request.user.acl['visible_categories']
  105. ).select_related('parent'))
  106. def get_category(self, request, categories, **kwargs):
  107. return categories[0]
  108. def get_extra_context(self, request):
  109. return {
  110. 'is_index': not settings.MISAGO_CATEGORIES_ON_INDEX
  111. }
  112. def set_frontend_context(self, request):
  113. request.frontend_context.update({
  114. 'THREADS_API': reverse('misago:api:thread-list'),
  115. })
  116. class CategoryThreadsList(ThreadsList, ThreadsListMixin):
  117. template_name = 'misago/threadslist/category.html'
  118. preloaded_data_prefix = 'CATEGORY_'
  119. def get_category(self, request, categories, **kwargs):
  120. for category in categories:
  121. if category.pk == int(kwargs['category_id']):
  122. if category.special_role:
  123. raise Http404()
  124. allow_see_category(request.user, category)
  125. allow_browse_category(request.user, category)
  126. validate_slug(category, kwargs['category_slug'])
  127. return category
  128. else:
  129. raise Http404()
  130. class PrivateThreadsList(ThreadsList):
  131. template_name = 'misago/threadslist/private_threads.html'
  132. preloaded_data_prefix = 'PRIVATE_'
  133. def get_category(self, request, **kwargs):
  134. return Category.objects.private_threads()
  135. def get_subcategories(self, request, category):
  136. return []