lists.py 6.6 KB

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