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

Changed search views for objects as preparation for #149.

Ralfp 12 лет назад
Родитель
Сommit
7d6f26bf02

+ 18 - 21
misago/apps/privatethreads/search.py

@@ -1,27 +1,24 @@
-from misago.decorators import block_crawlers
 from misago.models import Post
-from misago.apps.errors import error404
-from misago.apps.search.views import do_search, results
+from misago.acl.exceptions import ACLError404
+from misago.apps.search.views import SearchBaseView, ResultsBaseView
 
-def allow_search(f):
-    def decorator(*args, **kwargs):
-        request = args[0]
-        if not (request.acl.private_threads.can_participate()
-                and request.settings['enable_private_threads']):
-            return error404()
-        return f(*args, **kwargs)
-    return decorator
+class SearchPrivateThreadsMixin(object):
+    search_route = 'private_threads_search'
+    results_route = 'private_threads_results'
 
+    def check_acl(self):
+        if not (self.request.acl.private_threads.can_participate()
+                and self.request.settings['enable_private_threads']):
+            raise ACLError404()
 
-@block_crawlers
-@allow_search
-def search_private_threads(request):
-    threads = [t.pk for t in request.user.private_thread_set.all()]
-    queryset = Post.objects.filter(thread_id__in=threads)
-    return do_search(request, queryset, 'private_threads')
+    def queryset(self):
+        threads = [t.pk for t in self.request.user.private_thread_set.all()]
+        return Post.objects.filter(thread_id__in=threads)
 
 
-@block_crawlers
-@allow_search
-def show_private_threads_results(request, page=0):
-    return results(request, page, 'private_threads')
+class SearchView(SearchPrivateThreadsMixin, SearchBaseView):
+    pass
+
+
+class ResultsView(SearchPrivateThreadsMixin, ResultsBaseView):
+    pass

+ 3 - 3
misago/apps/privatethreads/urls.py

@@ -38,7 +38,7 @@ urlpatterns = patterns('misago.apps.privatethreads',
     url(r'^(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/(?P<change>\d+)/$', 'changelog.ChangelogDiffView', name="private_thread_changelog_diff"),
     url(r'^(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/(?P<change>\d+)/revert/$', 'changelog.ChangelogRevertView', name="private_thread_changelog_revert"),
     # Extra search routes
-    url(r'^search/$', 'search.search_private_threads', name="private_threads_search"),
-    url(r'^search/results/$', 'search.show_private_threads_results', name="private_threads_results"),
-    url(r'^search/results/(?P<page>[1-9]([0-9]+)?)/$', 'search.show_private_threads_results', name="private_threads_results"),
+    url(r'^search/$', 'search.SearchView', name="private_threads_search"),
+    url(r'^search/results/$', 'search.SearchView', name="private_threads_results"),
+    url(r'^search/results/(?P<page>[1-9]([0-9]+)?)/$', 'search.ResultsView', name="private_threads_results"),
 )

+ 16 - 19
misago/apps/reports/search.py

@@ -1,25 +1,22 @@
-from misago.decorators import block_crawlers
 from misago.models import Forum, Post
-from misago.apps.errors import error404
-from misago.apps.search.views import do_search, results
+from misago.acl.exceptions import ACLError404
+from misago.apps.search.views import SearchBaseView, ResultsBaseView
 
-def allow_search(f):
-    def decorator(*args, **kwargs):
-        request = args[0]
-        if not request.acl.reports.can_handle():
-            return error404()
-        return f(*args, **kwargs)
-    return decorator
+class SearchReportsMixin(object):
+    search_route = 'reports_search'
+    results_route = 'reports_results'
+    
+    def check_acl(self):
+        if not self.request.acl.reports.can_handle():
+            raise ACLError404()
 
+    def queryset(self):
+        return Post.objects.filter(forum=Forum.objects.special_pk('reports'))
 
-@block_crawlers
-@allow_search
-def search_reports(request):
-    queryset = Post.objects.filter(forum=Forum.objects.special_pk('reports'))
-    return do_search(request, queryset, 'reports')
 
+class SearchView(SearchReportsMixin, SearchBaseView):
+    pass
 
-@block_crawlers
-@allow_search
-def show_reports_results(request, page=0):
-    return results(request, page, 'reports')
+
+class ResultsView(SearchReportsMixin, ResultsBaseView):
+    pass

+ 3 - 3
misago/apps/reports/urls.py

@@ -30,7 +30,7 @@ urlpatterns = patterns('misago.apps.reports',
     url(r'^(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/(?P<change>\d+)/$', 'changelog.ChangelogDiffView', name="report_changelog_diff"),
     url(r'^(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/(?P<change>\d+)/revert/$', 'changelog.ChangelogRevertView', name="report_changelog_revert"),
     # Extra search routes
-    url(r'^search/$', 'search.search_reports', name="reports_search"),
-    url(r'^search/results/$', 'search.show_reports_results', name="reports_results"),
-    url(r'^search/results/(?P<page>[1-9]([0-9]+)?)/$', 'search.show_reports_results', name="reports_results"),
+    url(r'^search/$', 'search.SearchView', name="reports_search"),
+    url(r'^search/results/$', 'search.SearchView', name="reports_results"),
+    url(r'^search/results/(?P<page>[1-9]([0-9]+)?)/$', 'search.ResultsView', name="reports_results"),
 )

+ 0 - 7
misago/apps/search/urls.py

@@ -1,7 +0,0 @@
-from django.conf.urls import patterns, url
-
-urlpatterns = patterns('misago.apps.search.views',
-    url(r'^$', 'search', name="search"),
-    url(r'^results/$', 'show_results', name="search_results"),
-    url(r'^results/(?P<page>[1-9]([0-9]+)?)/$', 'show_results', name="search_results"),
-)

+ 114 - 103
misago/apps/search/views.py

@@ -5,6 +5,7 @@ from django.template import RequestContext
 from django.utils import timezone
 from django.utils.translation import ugettext as _
 from haystack.query import RelatedSearchQuerySet
+from misago.acl.exceptions import ACLError403, ACLError404
 from misago.decorators import block_crawlers
 from misago.forms import FormFields
 from misago.models import Forum, Thread, Post, User
@@ -14,112 +15,122 @@ from misago.apps.errors import error403, error404
 from misago.apps.profiles.views import list as users_list
 from misago.apps.search.forms import QuickSearchForm
 
-@block_crawlers
-def search(request):
-    queryset = Post.objects.filter(forum__in=Forum.objects.readable_forums(request.acl))
-    return do_search(request, queryset)
 
+class ViewBase(object):
+    search_route = 'search'
+    results_route = 'search_results'
+    advanced_route = None
 
-def do_search(request, queryset, search_route=None):
-    if not request.acl.search.can_search():
-        return error403(request, _("You don't have permission to search community."))
+    def check_acl(self):
+        pass
 
-    search_route = search_route or 'search'
+    def queryset(self):
+        pass
 
-    if request.method != "POST":
-        form = QuickSearchForm(request=request)
-        return request.theme.render_to_response('search/home.html',
-                                                {
-                                                 'form': FormFields(form),
-                                                 'search_route': search_route,
-                                                 'search_result': request.session.get('%s_result' % search_route),
-                                                 'disable_search': True,
-                                                },
-                                                context_instance=RequestContext(request))
+    def search_form_type(self):
+        return QuickSearchForm
+
+    def render_to_response(self, template, form, context):
+        context.update({
+                        'form': FormFields(form),
+                        'search_route': self.search_route,
+                        'results_route': self.results_route,
+                        'search_advanced': self.advanced_route,
+                        'disable_search': True,
+                        })
+        return self.request.theme.render_to_response('search/%s.html' % template,
+                                                     context,
+                                                     context_instance=RequestContext(self.request))
+
+    def __new__(cls, request, **kwargs):
+        obj = super(ViewBase, cls).__new__(cls)
+        return obj(request, **kwargs)
+
+    def __call__(self, request, **kwargs):
+        try:
+            if request.user.is_crawler():
+                raise ACLError404()
+            self.check_acl()
+            if not request.acl.search.can_search():
+                raise ACLError403(_("You don't have permission to search community."))
+            self.request = request
+            return self.call(**kwargs)
+        except ACLError403 as e:
+            return error403(request, unicode(e))
+        except ACLError404 as e:
+            return error404(request, unicode(e))
+
+
+class SearchBaseView(ViewBase):
+    def call(self, **kwargs):
+        form_type = self.search_form_type()
+        if self.request.method != "POST":
+            form = self.search_form_type()(request=self.request)
+            return self.render_to_response('home', form,  
+                                           {
+                                            'search_result': self.request.session.get(self.results_route),
+                                           })
         
-    try:
-        form = QuickSearchForm(request.POST, request=request)
-        if form.is_valid():
-            if form.mode == 'forum':
-                jump_to = Forum.objects.forum_by_name(form.target, request.acl)
-                if jump_to:
-                    if jump_to.level == 1:
-                        return redirect(reverse('index') + ('#%s' % jump_to.slug))
-                    return redirect(jump_to.url)
-                else:
-                    raise SearchException(_('Forum "%(forum)s" could not be found.') % {'forum': form.target})
-            if form.mode == 'user':
-                request.POST = request.POST.copy()
-                request.POST['username'] = form.target
-                return users_list(request)
-            sqs = RelatedSearchQuerySet().auto_query(form.cleaned_data['search_query']).order_by('-id').load_all()
-            sqs = sqs.load_all_queryset(Post, queryset.filter(deleted=False).filter(moderated=False).select_related('thread', 'forum', 'user'))[:60]
-
-            if request.user.is_authenticated():
-                request.user.last_search = timezone.now()
-                request.user.save(force_update=True)
-            if request.user.is_anonymous():
-                request.session['last_search'] = timezone.now()
-
-            if not sqs:
-                raise SearchException(_("Search returned no results. Change search query and try again."))
-            request.session['%s_result' % search_route] = {
-                                                           'search_query': form.cleaned_data['search_query'],
-                                                           'search_results': [p.object for p in sqs],
-                                                           }
-            return redirect(reverse('%s_results' % search_route))
-        else:
-            raise SearchException(form.errors['search_query'][0])
-    except SearchException as e:
-        return request.theme.render_to_response('search/error.html',
-                                                {
-                                                 'form': FormFields(form),
-                                                 'search_route': search_route,
-                                                 'message': unicode(e),
-                                                 'disable_search': True,
-                                                },
-                                                context_instance=RequestContext(request))
-
-
-@block_crawlers
-def show_results(request, page=0):
-    return results(request, page)
-
-
-def results(request, page=0, search_route=None):
-    if not request.acl.search.can_search():
-        return error403(request, _("You don't have permission to search community."))
-
-    search_route = search_route or 'search'
-    result = request.session.get('%s_result' % search_route)
-    if not result:
-        form = QuickSearchForm(request=request)
-        return request.theme.render_to_response('search/error.html',
-                                                {
-                                                 'form': FormFields(form),
-                                                 'search_route': search_route,
-                                                 'message': _("No search results were found."),
-                                                 'disable_search': True,
-                                                },
-                                                context_instance=RequestContext(request))
-
-    items = result['search_results']
-    items_total = len(items);
-    try:
-        pagination = make_pagination(page, items_total, 12)
-    except Http404:
-        return redirect(reverse('%s_results' % search_route))
-
-    form = QuickSearchForm(request=request, initial={'search_query': result['search_query']})
-    return request.theme.render_to_response('search/results.html',
-                                            {
-                                             'form': FormFields(form),
-                                             'search_route': search_route,
-                                             'search_query': result['search_query'],
-                                             'results': items[pagination['start']:pagination['stop']],
-                                             'disable_search': True,
-                                             'items_total': items_total,
-                                             'pagination': pagination,
-                                            },
-                                            context_instance=RequestContext(request))
+        try:
+            form = self.search_form_type()(self.request.POST, request=self.request)
+            if form.is_valid():
+                if form.mode == 'forum':
+                    jump_to = Forum.objects.forum_by_name(form.target, self.request.acl)
+                    if jump_to:
+                        if jump_to.level == 1:
+                            return redirect(reverse('index') + ('#%s' % jump_to.slug))
+                        return redirect(jump_to.url)
+                    else:
+                        raise SearchException(_('Forum "%(forum)s" could not be found.') % {'forum': form.target})
+                if form.mode == 'user':
+                    self.request.POST = self.request.POST.copy()
+                    self.request.POST['username'] = form.target
+                    return users_list(self.request)
+                sqs = RelatedSearchQuerySet().auto_query(form.cleaned_data['search_query']).order_by('-id').load_all()
+                sqs = sqs.load_all_queryset(Post, self.queryset().filter(deleted=False).filter(moderated=False).select_related('thread', 'forum', 'user'))[:60]
+
+                if self.request.user.is_authenticated():
+                    self.request.user.last_search = timezone.now()
+                    self.request.user.save(force_update=True)
+                if self.request.user.is_anonymous():
+                    self.request.session['last_search'] = timezone.now()
+
+                if not sqs:
+                    raise SearchException(_("Search returned no results. Change search query and try again."))
+                self.request.session[self.results_route] = {
+                                                               'search_query': form.cleaned_data['search_query'],
+                                                               'search_results': [p.object for p in sqs],
+                                                               }
+                return redirect(reverse(self.results_route))
+            else:
+                if 'search_query' in form.errors:
+                    raise SearchException(form.errors['search_query'][0])
+                raise SearchException(form.errors['__all__'][0])
+        except SearchException as e:
+            return self.render_to_response('error', form,  
+                                           {'message': unicode(e)})
+
+
+class ResultsBaseView(ViewBase):
+    def call(self, **kwargs):
+        result = self.request.session.get(self.results_route)
+        if not result:
+            form = self.search_form_type()(request=self.request)
+            return self.render_to_response('error', form,  
+                                           {'message': _("No search results were found.")})
+
+        items = result['search_results']
+        items_total = len(items);
+        try:
+            pagination = make_pagination(kwargs.get('page', 0), items_total, 12)
+        except Http404:
+            return redirect(reverse(self.search_route))
 
+        form = self.search_form_type()(request=self.request, initial={'search_query': result['search_query']})
+        return self.render_to_response('results', form,  
+                                       {
+                                        'search_query': result['search_query'],
+                                        'results': items[pagination['start']:pagination['stop']],
+                                        'items_total': items_total,
+                                        'pagination': pagination,
+                                       })

+ 14 - 0
misago/apps/threads/search.py

@@ -0,0 +1,14 @@
+from misago.models import Forum, Post
+from misago.apps.search.views import SearchBaseView, ResultsBaseView
+
+class SearchThreadsMixin(object):
+    def queryset(self):
+        return Post.objects.filter(forum__in=Forum.objects.readable_forums(self.request.acl))
+
+
+class SearchView(SearchThreadsMixin, SearchBaseView):
+    pass
+
+
+class ResultsView(SearchThreadsMixin, ResultsBaseView):
+    pass

+ 4 - 0
misago/apps/threads/urls.py

@@ -38,4 +38,8 @@ urlpatterns = patterns('misago.apps.threads',
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/$', 'changelog.ChangelogView', name="thread_changelog"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/(?P<change>\d+)/$', 'changelog.ChangelogDiffView', name="thread_changelog_diff"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/(?P<change>\d+)/revert/$', 'changelog.ChangelogRevertView', name="thread_changelog_revert"),
+    # Searching
+    url(r'^search/$', 'search.SearchView', name="search"),
+    url(r'^search/results/$', 'search.ResultsView', name="search_results"),
+    url(r'^search/results/(?P<page>[1-9]([0-9]+)?)/$', 'search.ResultsView', name="search_results"),
 )

+ 0 - 1
misago/urls.py

@@ -29,7 +29,6 @@ urlpatterns += patterns('',
     (r'^reset-password/', include('misago.apps.resetpswd.urls')),
     (r'^private-threads/', include('misago.apps.privatethreads.urls')),
     (r'^reports/', include('misago.apps.reports.urls')),
-    (r'^search/', include('misago.apps.search.urls')),
     (r'^', include('misago.apps.threads.urls')),
 )
 

+ 1 - 1
templates/cranefly/search/home.html

@@ -13,5 +13,5 @@
 {% endblock %}
 
 {% macro style_query(query) -%}
-<a href="{{ ('%s_results'|format(search_route))|url }}">{{ query }}</a>
+<a href="{{ results_route|url }}">{{ query }}</a>
 {%- endmacro %}