lists.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. from django.http import Http404
  2. from rest_framework.response import Response
  3. from misago.acl import add_acl
  4. from misago.categories.models import Category
  5. from misago.categories.permissions import allow_see_category, allow_browse_category
  6. from misago.core.shortcuts import get_int_or_404, paginate, pagination_dict
  7. from misago.readtracker import threadstracker
  8. from misago.threads.mixins.threadslist import ThreadsListMixin
  9. from misago.threads.permissions.privatethreads import allow_use_private_threads
  10. from misago.threads.serializers import ThreadListSerializer
  11. from misago.threads.subscriptions import make_subscription_aware
  12. from misago.threads.utils import add_categories_to_threads
  13. LIST_TYPES = (
  14. 'all',
  15. 'my',
  16. 'new',
  17. 'unread',
  18. 'subscribed',
  19. 'unapproved',
  20. )
  21. class BaseListEndpoint(ThreadsListMixin):
  22. serialize_subcategories = True
  23. def __call__(self, request):
  24. try:
  25. page_no = int(request.query_params.get('page', 0))
  26. except (ValueError, TypeError):
  27. raise Http404()
  28. list_type = request.query_params.get('list') or 'all'
  29. if list_type not in LIST_TYPES:
  30. raise Http404()
  31. categories = self.get_categories(request)
  32. category = self.get_category(request, categories)
  33. self.allow_see_list(request, category, list_type)
  34. subcategories = self.get_subcategories(category, categories)
  35. base_queryset = self.get_base_queryset(request, categories, list_type)
  36. threads_categories = [category] + subcategories
  37. threads_queryset = self.get_threads_queryset(category, base_queryset, threads_categories)
  38. page = paginate(threads_queryset, page_no, 24, 6, allow_explicit_first_page=True)
  39. response_dict = pagination_dict(page, include_page_range=False)
  40. if page.number > 1:
  41. threads = list(page.object_list)
  42. else:
  43. pinned_threads = self.get_pinned_threads(category, base_queryset, threads_categories)
  44. threads = list(pinned_threads) + list(page.object_list)
  45. if list_type in ('new', 'unread'):
  46. # we already know all threads on list are unread
  47. threadstracker.make_unread(threads)
  48. else:
  49. threadstracker.make_threads_read_aware(request.user, threads)
  50. add_categories_to_threads(category, categories, threads)
  51. if self.serialize_subcategories:
  52. response_dict['subcategories'] = []
  53. visible_subcategories = self.get_visible_subcategories(threads, threads_categories)
  54. for subcategory in subcategories:
  55. if subcategory in visible_subcategories:
  56. response_dict['subcategories'].append(subcategory.pk)
  57. add_acl(request.user, threads)
  58. make_subscription_aware(request.user, threads)
  59. response_dict['results'] = ThreadListSerializer(threads, many=True).data
  60. return Response(response_dict)
  61. class ThreadsListEndpoint(BaseListEndpoint):
  62. def get_category(self, request, categories):
  63. if request.query_params.get('category'):
  64. category_id = get_int_or_404(request.query_params['category'])
  65. for category in categories:
  66. if category.pk == category_id:
  67. if category.level:
  68. allow_see_category(request.user, category)
  69. allow_browse_category(request.user, category)
  70. return category
  71. else:
  72. raise Http404() # disallow root category access
  73. raise Http404()
  74. return categories[0]
  75. def get_pinned_threads(self, category, queryset, threads_categories):
  76. if category.level:
  77. return list(queryset.filter(weight=2)) + list(queryset.filter(
  78. weight=1,
  79. category__in=threads_categories
  80. ))
  81. else:
  82. return queryset.filter(weight=2)
  83. def get_threads_queryset(self, category, queryset, threads_categories):
  84. if category.level:
  85. return queryset.filter(
  86. weight=0,
  87. category__in=threads_categories,
  88. )
  89. else:
  90. return queryset.filter(
  91. weight__lt=2,
  92. category__in=threads_categories,
  93. )
  94. threads_list_endpoint = ThreadsListEndpoint()
  95. class PrivateThreadsListEndpoint(BaseListEndpoint):
  96. def get_category(self, request, categories):
  97. allow_use_private_threads(request.user)
  98. return Category.objects.private_threads()
  99. def get_subcategories(self, category, categories):
  100. return []
  101. def get_pinned_threads(self, category, queryset, threads_categories):
  102. return []
  103. def get_threads_queryset(self, category, queryset, threads_categories):
  104. return queryset.filter(category__in=threads_categories)
  105. private_threads_list_endpoint = PrivateThreadsListEndpoint()