Просмотр исходного кода

Handle 404 on incorrect page number

Ralfp 12 лет назад
Родитель
Сommit
5e1dd2b1b4

+ 7 - 41
misago/apps/admin/widgets.py

@@ -1,6 +1,7 @@
 from django import forms
 from django.core.exceptions import ValidationError
 from django.core.urlresolvers import reverse
+from django.http import Http404
 from django.shortcuts import redirect
 from django.template import RequestContext
 from django.utils.translation import ugettext_lazy as _
@@ -8,6 +9,7 @@ from jinja2 import TemplateNotFound
 import math
 from misago.forms import Form, FormLayout, FormFields, FormFieldsets
 from misago.messages import Message
+from misago.utils.pagination import make_pagination
 
 """
 Class widgets
@@ -207,46 +209,7 @@ class ListWidget(BaseWidget):
         return reverse(self.admin.get_action_attr(self.id, 'route'), kwargs={'page': page})
 
     def get_pagination(self, total, page):
-        """
-        Return list pagination.
-        A list with three values:
-        - Offset for ORM slicing
-        - Length of slice
-        - no. of prev page (or -1 for first page)
-        - no. of next page (or -1 for last page)
-        - Current page
-        - Pages total
-        """
-        if not self.pagination or total < 0:
-            # Dont do anything if we are not paging
-            return None
-
-        # Set basic pagination, use either Session cache or new page value
-        pagination = {'start': 0, 'stop': 0, 'prev':-1, 'next':-1}
-        if self.request.session.get(self.get_token('pagination')):
-            pagination['start'] = self.request.session.get(self.get_token('pagination'))
-        page = int(page)
-        if page > 0:
-            pagination['start'] = (page - 1) * self.pagination
-
-        # Set page and total stat
-        pagination['page'] = int(pagination['start'] / self.pagination) + 1
-        pagination['total'] = int(math.ceil(total / float(self.pagination)))
-
-        # Fix too large offset
-        if pagination['start'] > total:
-            pagination['start'] = 0
-
-        # Allow prev/next?
-        if total > self.pagination:
-            if pagination['page'] > 1:
-                pagination['prev'] = pagination['page'] - 1
-            if pagination['page'] < pagination['total']:
-                pagination['next'] = pagination['page'] + 1
-
-        # Set stop offset
-        pagination['stop'] = pagination['start'] + self.pagination
-        return pagination
+        return make_pagination(page, total, self.pagination)
 
     def get_items(self):
         if self.request.session.get(self.get_token('filter')):
@@ -271,7 +234,10 @@ class ListWidget(BaseWidget):
 
         # Set sorting and paginating
         sorting_method = self.get_sorting()
-        paginating_method = self.get_pagination(items_total, page)
+        try:
+            paginating_method = self.get_pagination(items_total, page)
+        except Http404:
+            return redirect(self.get_url())
 
         # List items
         items = self.get_items()

+ 7 - 1
misago/apps/newthreads.py

@@ -1,4 +1,7 @@
 from datetime import timedelta
+from django.core.urlresolvers import reverse
+from django.http import Http404
+from django.shortcuts import redirect
 from django.template import RequestContext
 from django.utils import timezone
 from misago.models import Forum, Thread
@@ -7,7 +10,10 @@ from misago.utils.pagination import make_pagination
 def new_threads(request, page=0):
     queryset = Thread.objects.filter(forum_id__in=Forum.objects.readable_forums(request.acl)).filter(deleted=False).filter(moderated=False).filter(start__gte=(timezone.now() - timedelta(days=2)))
     items_total = queryset.count();
-    pagination = make_pagination(page, items_total, 30)
+    try:
+        pagination = make_pagination(page, items_total, 30)
+    except Http404:
+        return redirect(reverse('new_threads'))
 
     queryset = queryset.order_by('-start').prefetch_related('forum')[pagination['start']:pagination['stop']];
     if request.settings['avatars_on_threads_list']:

+ 7 - 1
misago/apps/popularthreads.py

@@ -1,4 +1,7 @@
 from datetime import timedelta
+from django.core.urlresolvers import reverse
+from django.http import Http404
+from django.shortcuts import redirect
 from django.template import RequestContext
 from django.utils import timezone
 from misago.models import Forum, Thread
@@ -7,7 +10,10 @@ from misago.utils.pagination import make_pagination
 def popular_threads(request, page=0):
     queryset = Thread.objects.filter(forum_id__in=Forum.objects.readable_forums(request.acl)).filter(deleted=False).filter(moderated=False)
     items_total = queryset.count();
-    pagination = make_pagination(page, items_total, 30)
+    try:
+        pagination = make_pagination(page, items_total, 30)
+    except Http404:
+        return redirect(reverse('popular_threads'))
 
     queryset = queryset.order_by('-score').prefetch_related('forum')[pagination['start']:pagination['stop']];
     if request.settings['avatars_on_threads_list']:

+ 5 - 1
misago/apps/privatethreads/list.py

@@ -1,4 +1,5 @@
 from itertools import chain
+from django.http import Http404
 from django.utils.translation import ugettext as _
 from misago.apps.threadtype.list import ThreadsListBaseView, ThreadsListModeration
 from misago.models import Forum, Thread
@@ -21,7 +22,10 @@ class ThreadsListView(ThreadsListBaseView, ThreadsListModeration, TypeMixin):
             qs_threads = qs_threads.prefetch_related('start_poster', 'last_poster')
 
         self.count = qs_threads.count()
-        self.pagination = make_pagination(self.kwargs.get('page', 0), self.count, self.request.settings.threads_per_page)
+        try:
+            self.pagination = make_pagination(self.kwargs.get('page', 0), self.count, self.request.settings.threads_per_page)
+        except Http404:
+            return self.threads_list_redirect()
 
         tracker_forum = ThreadsTracker(self.request, self.forum)
         for thread in qs_threads[self.pagination['start']:self.pagination['stop']]:

+ 7 - 1
misago/apps/profiles/followers/views.py

@@ -1,3 +1,6 @@
+from django.core.urlresolvers import reverse
+from django.http import Http404
+from django.shortcuts import redirect
 from misago.apps.profiles.decorators import profile_view
 from misago.apps.profiles.template import RequestContext
 from misago.utils.pagination import make_pagination
@@ -6,7 +9,10 @@ from misago.utils.pagination import make_pagination
 def followers(request, user, page=0):
     queryset = user.follows_set.order_by('username_slug')
     count = queryset.count()
-    pagination = make_pagination(page, count, 24)
+    try:
+        pagination = make_pagination(page, count, 24)
+    except Http404:
+        return redirect(reverse('user_followers', kwargs={'user': user.id, 'username': user.username_slug}))
     
     return request.theme.render_to_response('profiles/followers.html',
                                             context_instance=RequestContext(request, {

+ 8 - 2
misago/apps/profiles/follows/views.py

@@ -1,13 +1,19 @@
+from django.core.urlresolvers import reverse
+from django.http import Http404
+from django.shortcuts import redirect
 from misago.apps.profiles.decorators import profile_view
 from misago.apps.profiles.template import RequestContext
 from misago.utils.pagination import make_pagination
 
 @profile_view('user_follows')
 def follows(request, user, page=0):
-    
     queryset = user.follows.order_by('username_slug')
     count = queryset.count()
-    pagination = make_pagination(page, count, 24)
+    try:
+        pagination = make_pagination(page, count, 24)
+    except Http404:
+        return redirect(reverse('user_follows', kwargs={'user': user.id, 'username': user.username_slug}))
+
     return request.theme.render_to_response('profiles/follows.html',
                                             context_instance=RequestContext(request, {
                                              'profile': user,

+ 8 - 1
misago/apps/profiles/posts/views.py

@@ -1,3 +1,6 @@
+from django.core.urlresolvers import reverse
+from django.http import Http404
+from django.shortcuts import redirect
 from misago.apps.profiles.decorators import profile_view
 from misago.apps.profiles.template import RequestContext
 from misago.models import Forum
@@ -7,7 +10,11 @@ from misago.utils.pagination import make_pagination
 def posts(request, user, page=0):
     queryset = user.post_set.filter(forum_id__in=Forum.objects.readable_forums(request.acl)).filter(deleted=False).filter(moderated=False).select_related('thread', 'forum').order_by('-id')
     count = queryset.count()
-    pagination = make_pagination(page, count, 12)
+    try:
+        pagination = make_pagination(page, count, 12)
+    except Http404:
+        return redirect(reverse('user_posts', kwargs={'user': user.id, 'username': user.username_slug}))
+    
     return request.theme.render_to_response('profiles/posts.html',
                                             context_instance=RequestContext(request, {
                                              'profile': user,

+ 7 - 1
misago/apps/profiles/threads/views.py

@@ -1,3 +1,6 @@
+from django.core.urlresolvers import reverse
+from django.http import Http404
+from django.shortcuts import redirect
 from misago.apps.profiles.decorators import profile_view
 from misago.apps.profiles.template import RequestContext
 from misago.models import Forum
@@ -7,7 +10,10 @@ from misago.utils.pagination import make_pagination
 def threads(request, user, page=0):
     queryset = user.thread_set.filter(forum_id__in=Forum.objects.readable_forums(request.acl)).filter(deleted=False).filter(moderated=False).select_related('start_post', 'forum').order_by('-id')
     count = queryset.count()
-    pagination = make_pagination(page, count, 12)
+    try:
+        pagination = make_pagination(page, count, 12)
+    except Http404:
+        return redirect(reverse('user_threads', kwargs={'user': user.id, 'username': user.username_slug}))
     
     return request.theme.render_to_response('profiles/threads.html',
                                             context_instance=RequestContext(request, {

+ 7 - 1
misago/apps/profiles/views.py

@@ -1,4 +1,5 @@
 from django.core.urlresolvers import reverse
+from django.http import Http404
 from django.shortcuts import redirect
 from django.template import RequestContext
 from misago.apps.errors import error403, error404
@@ -71,7 +72,12 @@ def list(request, slug=None, page=1):
         if active_rank:
             users = User.objects.filter(rank=active_rank)
             items_total = users.count()
-            pagination = make_pagination(page, items_total, request.settings['profiles_per_list'])
+            try:
+                pagination = make_pagination(page, items_total, request.settings['profiles_per_list'])
+            except Http404:
+                if not default_rank and active_rank:
+                    return redirect(reverse('users', kwargs={'slug': active_rank.slug}))
+                return redirect(reverse('users'))
             users = users.order_by('username_slug')[pagination['start']:pagination['stop']]
 
     return request.theme.render_to_response('profiles/list.html',

+ 8 - 1
misago/apps/threads/list.py

@@ -1,4 +1,7 @@
 from itertools import chain
+from django.core.urlresolvers import reverse
+from django.http import Http404
+from django.shortcuts import redirect
 from django.utils.translation import ugettext as _
 from misago.apps.threadtype.list import ThreadsListBaseView, ThreadsListModeration
 from misago.models import Forum, Thread
@@ -30,7 +33,11 @@ class ThreadsListView(ThreadsListBaseView, ThreadsListModeration, TypeMixin):
     def fetch_threads(self):
         qs_announcements, qs_threads = self.threads_queryset()
         self.count = qs_threads.count()
-        self.pagination = make_pagination(self.kwargs.get('page', 0), self.count, self.request.settings.threads_per_page)
+
+        try:
+            self.pagination = make_pagination(self.kwargs.get('page', 0), self.count, self.request.settings.threads_per_page)
+        except Http404:
+            return self.threads_list_redirect()
 
         tracker_forum = ThreadsTracker(self.request, self.forum)
         for thread in list(chain(qs_announcements, qs_threads[self.pagination['start']:self.pagination['stop']])):

+ 0 - 1
misago/apps/threadtype/changelog.py

@@ -10,7 +10,6 @@ from misago.messages import Message
 from misago.models import Forum, Thread, Post, Change
 from misago.utils.datesformats import reldate
 from misago.utils.strings import slugify
-from misago.utils.pagination import make_pagination
 from misago.apps.threadtype.base import ViewBase
 
 class ChangelogBaseView(ViewBase):

+ 0 - 1
misago/apps/threadtype/jumps.py

@@ -8,7 +8,6 @@ from misago.decorators import block_guest, check_csrf
 from misago.messages import Message
 from misago.models import Forum, Thread, Post, Karma, WatchedThread
 from misago.readstrackers import ThreadsTracker
-from misago.utils.pagination import make_pagination
 from misago.utils.views import json_response
 from misago.apps.threadtype.base import ViewBase
 

+ 3 - 1
misago/apps/threadtype/list/views.py

@@ -97,7 +97,9 @@ class ThreadsListBaseView(ViewBase):
             self._type_available()
             self._fetch_forum()
             self._check_permissions()
-            self.fetch_threads()
+            response = self.fetch_threads()
+            if response:
+                return response
             self.form = None
             self.make_form()
             if self.form:

+ 9 - 2
misago/apps/threadtype/thread/views.py

@@ -1,6 +1,7 @@
 from django import forms
 from django.core.urlresolvers import reverse
 from django.forms import ValidationError
+from django.http import Http404
 from django.shortcuts import redirect
 from django.template import RequestContext
 from django.utils import timezone
@@ -42,7 +43,11 @@ class ThreadBaseView(ViewBase):
         else:
             self.posts = self.posts.order_by('pk')
 
-        self.pagination = make_pagination(self.kwargs.get('page', 0), self.count, self.request.settings.posts_per_page)
+        try:
+            self.pagination = make_pagination(self.kwargs.get('page', 0), self.count, self.request.settings.posts_per_page)
+        except Http404:
+            return redirect(reverse(self.type_prefix, kwargs={'thread': self.thread.pk, 'slug': self.thread.slug}))
+
         if self.request.settings.posts_per_page < self.count:
             self.posts = self.posts[self.pagination['start']:self.pagination['stop']]
 
@@ -178,7 +183,9 @@ class ThreadBaseView(ViewBase):
             self.fetch_thread()
             self.check_forum_type()
             self._check_permissions()
-            self.fetch_posts()
+            response = self.fetch_posts()
+            if response:
+                return response
             self.make_thread_form()
             if self.thread_form:
                 response = self.handle_thread_form()

+ 7 - 1
misago/apps/watchedthreads/views.py

@@ -1,6 +1,7 @@
 from django import forms
 from django.core.urlresolvers import reverse
 from django.db.models import F
+from django.http import Http404
 from django.shortcuts import redirect
 from django.template import RequestContext
 from django.utils.translation import ugettext as _
@@ -20,7 +21,12 @@ def watched_threads(request, page=0, new=False):
     if new:
         queryset = queryset.filter(last_read__lt=F('thread__last'))
     count = queryset.count()
-    pagination = make_pagination(page, count, request.settings.threads_per_page)
+    try:
+        pagination = make_pagination(page, count, request.settings.threads_per_page)
+    except Http404:
+        if new:
+            return redirect(reverse('watched_threads_new'))
+        return redirect(reverse('watched_threads'))
     queryset = queryset.order_by('-thread__last')
     if request.settings.threads_per_page < count:
         queryset = queryset[pagination['start']:pagination['stop']]