123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- from math import ceil
- from django.core.exceptions import PermissionDenied
- from django.db.models import Q
- from django.shortcuts import get_object_or_404, redirect
- from django.utils.translation import gettext as _
- from django.views import View
- from ...conf import settings
- from ...readtracker.dates import get_cutoff_date
- from ..permissions import exclude_invisible_posts
- from ..viewmodels import ForumThread, PrivateThread
- class GotoView(View):
- thread = None
- def get(self, request, pk, slug, **kwargs):
- thread = self.get_thread(request, pk, slug).unwrap()
- self.test_permissions(request, thread)
- posts_queryset = exclude_invisible_posts(
- request.user_acl, thread.category, thread.post_set
- )
- target_post = self.get_target_post(
- request.user, thread, posts_queryset.order_by("id"), **kwargs
- )
- target_page = self.compute_post_page(target_post, posts_queryset)
- return self.get_redirect(thread, target_post, target_page)
- def get_thread(self, request, pk, slug):
- return self.thread(request, pk, slug) # pylint: disable=not-callable
- def test_permissions(self, request, thread):
- pass
- def get_target_post(self, user, thread, posts_queryset):
- raise NotImplementedError(
- "goto views should define their own get_target_post method"
- )
- def compute_post_page(self, target_post, posts_queryset):
- # filter out events, order queryset
- posts_queryset = posts_queryset.filter(is_event=False).order_by("id")
- thread_length = posts_queryset.count()
- # is target an event?
- if target_post.is_event:
- target_event = target_post
- previous_posts = posts_queryset.filter(id__lt=target_event.id)
- else:
- previous_posts = posts_queryset.filter(id__lte=target_post.id)
- post_position = previous_posts.count()
- per_page = settings.MISAGO_POSTS_PER_PAGE - 1
- orphans = settings.MISAGO_POSTS_TAIL
- if orphans:
- orphans += 1
- hits = max(1, thread_length - orphans)
- thread_pages = int(ceil(hits / float(per_page)))
- if post_position >= thread_pages * per_page:
- return thread_pages
- return int(ceil(float(post_position) / (per_page)))
- def get_redirect(self, thread, target_post, target_page):
- thread_url = thread.thread_type.get_thread_absolute_url(thread, target_page)
- return redirect("%s#post-%s" % (thread_url, target_post.pk))
- class ThreadGotoPostView(GotoView):
- thread = ForumThread
- def get_target_post(self, user, thread, posts_queryset, **kwargs):
- return get_object_or_404(posts_queryset, pk=kwargs["post"])
- class ThreadGotoLastView(GotoView):
- thread = ForumThread
- def get_target_post(self, user, thread, posts_queryset, **kwargs):
- return posts_queryset.order_by("id").last()
- class GetFirstUnreadPostMixin:
- def get_first_unread_post(self, user, posts_queryset):
- if user.is_authenticated:
- expired_posts = Q(posted_on__lt=get_cutoff_date(user))
- read_posts = Q(id__in=user.postread_set.values("post"))
- first_unread = (
- posts_queryset.exclude(expired_posts | read_posts)
- .order_by("id")
- .first()
- )
- if first_unread:
- return first_unread
- return posts_queryset.order_by("id").last()
- class ThreadGotoNewView(GotoView, GetFirstUnreadPostMixin):
- thread = ForumThread
- def get_target_post(self, user, thread, posts_queryset, **kwargs):
- return self.get_first_unread_post(user, posts_queryset)
- class ThreadGotoBestAnswerView(GotoView):
- thread = ForumThread
- def get_target_post(self, user, thread, posts_queryset, **kwargs):
- return thread.best_answer or thread.first_post
- class ThreadGotoUnapprovedView(GotoView):
- thread = ForumThread
- def test_permissions(self, request, thread):
- if not thread.acl["can_approve"]:
- raise PermissionDenied(
- _(
- "You need permission to approve content to "
- "be able to go to first unapproved post."
- )
- )
- def get_target_post(self, user, thread, posts_queryset, **kwargs):
- unapproved_post = (
- posts_queryset.filter(is_unapproved=True).order_by("id").first()
- )
- if unapproved_post:
- return unapproved_post
- return posts_queryset.order_by("id").last()
- class PrivateThreadGotoPostView(GotoView):
- thread = PrivateThread
- def get_target_post(self, user, thread, posts_queryset, **kwargs):
- return get_object_or_404(posts_queryset, pk=kwargs["post"])
- class PrivateThreadGotoLastView(GotoView):
- thread = PrivateThread
- def get_target_post(self, user, thread, posts_queryset, **kwargs):
- return posts_queryset.order_by("id").last()
- class PrivateThreadGotoNewView(GotoView, GetFirstUnreadPostMixin):
- thread = PrivateThread
- def get_target_post(self, user, thread, posts_queryset, **kwargs):
- return self.get_first_unread_post(user, posts_queryset)
|