goto.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. from math import ceil
  2. from django.core.exceptions import PermissionDenied
  3. from django.shortcuts import get_object_or_404, redirect
  4. from django.utils.translation import ugettext as _
  5. from django.views.generic import View
  6. from misago.conf import settings
  7. from ..permissions.threads import exclude_invisible_posts
  8. from ..viewmodels.thread import ForumThread
  9. class GotoView(View):
  10. thread = None
  11. read_aware=False
  12. def get(self, request, pk, slug, **kwargs):
  13. thread = self.get_thread(request, pk, slug).unwrap()
  14. self.test_permissions(request, thread)
  15. posts_queryset = exclude_invisible_posts(request.user, thread.category, thread.post_set)
  16. target_post = self.get_target_post(thread, posts_queryset.order_by('id'), **kwargs)
  17. target_page = self.compute_post_page(target_post, posts_queryset)
  18. return self.get_redirect(thread, target_post, target_page)
  19. def get_thread(self, request, pk, slug):
  20. return self.thread(request, pk, slug, read_aware=self.read_aware)
  21. def test_permissions(self, request, thread):
  22. pass
  23. def get_target_post(self, thread, posts_queryset):
  24. raise NotImplementedError("goto views should define their own get_target_post method")
  25. def compute_post_page(self, target_post, posts_queryset):
  26. thread_len = posts_queryset.count()
  27. if thread_len <= settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL:
  28. return 1 # no chance for post to be on other page than only page
  29. # compute total count of thread pages
  30. thread_pages = thread_len // settings.MISAGO_POSTS_PER_PAGE
  31. thread_tail = thread_len - thread_pages * settings.MISAGO_POSTS_PER_PAGE
  32. if thread_tail > settings.MISAGO_POSTS_TAIL:
  33. thread_pages += 1
  34. # resolve post's page
  35. post_offset = posts_queryset.filter(pk__lte=target_post.pk).count()
  36. post_page = int(ceil(float(post_offset) / settings.MISAGO_POSTS_PER_PAGE))
  37. if post_page > thread_pages:
  38. post_page = thread_pages
  39. return post_page
  40. def get_redirect(self, thread, target_post, target_page):
  41. thread_url = thread.thread_type.get_thread_absolute_url(thread, target_page)
  42. return redirect('%s#post-%s' % (thread_url, target_post.pk))
  43. class ThreadGotoPostView(GotoView):
  44. thread = ForumThread
  45. def get_target_post(self, thread, posts_queryset, **kwargs):
  46. return get_object_or_404(posts_queryset, pk=kwargs['post'])
  47. class ThreadGotoLastView(GotoView):
  48. thread = ForumThread
  49. def get_target_post(self, thread, posts_queryset, **kwargs):
  50. return posts_queryset.order_by('id').last()
  51. class ThreadGotoNewView(GotoView):
  52. thread = ForumThread
  53. read_aware = True
  54. def get_target_post(self, thread, posts_queryset, **kwargs):
  55. if thread.is_new:
  56. return posts_queryset.filter(posted_on__gt=thread.last_read_on).order_by('id').first()
  57. else:
  58. return posts_queryset.order_by('id').last()
  59. class ThreadGotoUnapprovedView(GotoView):
  60. thread = ForumThread
  61. def test_permissions(self, request, thread):
  62. if not thread.acl['can_approve']:
  63. raise PermissionDenied(
  64. _("You need permission to approve content to be able to go to first unapproved post."))
  65. def get_target_post(self, thread, posts_queryset, **kwargs):
  66. unapproved_post = posts_queryset.filter(is_unapproved=True).order_by('id').first()
  67. if unapproved_post:
  68. return unapproved_post
  69. else:
  70. return posts_queryset.order_by('id').last()