posts.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. from ...acl.objectacl import add_acl_to_obj
  2. from ...core.shortcuts import paginate, pagination_dict
  3. from ...readtracker.poststracker import make_read_aware
  4. from ...users.online.utils import make_users_status_aware
  5. from ..paginator import PostsPaginator
  6. from ..permissions import exclude_invisible_posts
  7. from ..serializers import PostSerializer
  8. from ..utils import add_likes_to_posts
  9. __all__ = ["ThreadPosts"]
  10. class ViewModel:
  11. def __init__(self, request, thread, page): # pylint: disable=too-many-locals
  12. try:
  13. thread_model = thread.unwrap()
  14. except AttributeError:
  15. thread_model = thread
  16. posts_queryset = self.get_posts_queryset(request, thread_model)
  17. posts_limit = request.settings.posts_per_page
  18. posts_orphans = request.settings.posts_per_page_orphans
  19. list_page = paginate(
  20. posts_queryset, page, posts_limit, posts_orphans, paginator=PostsPaginator
  21. )
  22. paginator = pagination_dict(list_page)
  23. posts = list(list_page.object_list)
  24. posters = []
  25. for post in posts:
  26. post.category = thread.category
  27. post.thread = thread_model
  28. if post.poster:
  29. posters.append(post.poster)
  30. make_users_status_aware(request, posters)
  31. if thread.category.acl["can_see_posts_likes"]:
  32. add_likes_to_posts(request.user, posts)
  33. # add events to posts
  34. if thread_model.has_events:
  35. first_post = None
  36. if list_page.has_previous():
  37. first_post = posts[0]
  38. last_post = None
  39. if list_page.has_next():
  40. last_post = posts[-1]
  41. events_limit = request.settings.events_per_page
  42. posts += self.get_events_queryset(
  43. request, thread_model, events_limit, first_post, last_post
  44. )
  45. # sort both by pk
  46. posts.sort(key=lambda p: p.pk)
  47. # make posts and events ACL and reads aware
  48. add_acl_to_obj(request.user_acl, posts)
  49. make_read_aware(request, posts)
  50. self._user = request.user
  51. self.posts = posts
  52. self.paginator = paginator
  53. def get_posts_queryset(self, request, thread):
  54. queryset = (
  55. thread.post_set.select_related(
  56. "category",
  57. "poster",
  58. "poster__rank",
  59. "poster__ban_cache",
  60. "poster__online_tracker",
  61. )
  62. .filter(is_event=False)
  63. .order_by("id")
  64. )
  65. return exclude_invisible_posts(request.user_acl, thread.category, queryset)
  66. def get_events_queryset(
  67. self, request, thread, limit, first_post=None, last_post=None
  68. ):
  69. queryset = thread.post_set.select_related(
  70. "category",
  71. "poster",
  72. "poster__rank",
  73. "poster__ban_cache",
  74. "poster__online_tracker",
  75. ).filter(is_event=True)
  76. if first_post:
  77. queryset = queryset.filter(pk__gt=first_post.pk)
  78. if last_post:
  79. queryset = queryset.filter(pk__lt=last_post.pk)
  80. queryset = exclude_invisible_posts(request.user_acl, thread.category, queryset)
  81. return list(queryset.order_by("-id")[:limit])
  82. def get_frontend_context(self):
  83. context = {
  84. "results": PostSerializer(
  85. self.posts, many=True, context={"user": self._user}
  86. ).data
  87. }
  88. context.update(self.paginator)
  89. return context
  90. def get_template_context(self):
  91. return {"posts": self.posts, "paginator": self.paginator}
  92. class ThreadPosts(ViewModel):
  93. pass