Merge branch 'shipherd_hotfix'
[philo.git] / contrib / sobol / search.py
index cce3ec6..39b93c7 100644 (file)
@@ -25,9 +25,10 @@ __all__ = (
 
 SEARCH_CACHE_KEY = 'philo_sobol_search_results'
 DEFAULT_RESULT_TEMPLATE_STRING = "{% if url %}<a href='{{ url }}'>{% endif %}{{ title }}{% if url %}</a>{% endif %}"
+DEFAULT_RESULT_TEMPLATE = Template(DEFAULT_RESULT_TEMPLATE_STRING)
 
 # Determines the timeout on the entire result cache.
-MAX_CACHE_TIMEOUT = 60*60*24*7
+MAX_CACHE_TIMEOUT = 60*24*7
 
 
 class RegistrationError(Exception):
@@ -42,8 +43,9 @@ class SearchRegistry(object):
        def register(self, search, slug=None):
                slug = slug or search.slug
                if slug in self._registry:
-                       if self._registry[slug] != search:
-                               raise RegistrationError("A different search is already registered as `%s`")
+                       registered = self._registry[slug]
+                       if registered.__module__ != search.__module__:
+                               raise RegistrationError("A different search is already registered as `%s`" % slug)
                else:
                        self._registry[slug] = search
        
@@ -69,6 +71,9 @@ class SearchRegistry(object):
        
        def __getitem__(self, key):
                return self._registry[key]
+       
+       def __iter__(self):
+               return self._registry.__iter__()
 
 
 registry = SearchRegistry()
@@ -90,7 +95,10 @@ class Result(object):
                return self.search.get_result_title(self.result)
        
        def get_url(self):
-               return self.search.get_result_querydict(self.result).urlencode()
+               qd = self.search.get_result_querydict(self.result)
+               if qd is None:
+                       return ""
+               return "?%s" % qd.urlencode()
        
        def get_template(self):
                return self.search.get_result_template(self.result)
@@ -98,13 +106,17 @@ class Result(object):
        def get_extra_context(self):
                return self.search.get_result_extra_context(self.result)
        
-       def render(self):
-               t = self.get_template()
-               c = Context(self.get_extra_context())
-               c.update({
+       def get_context(self):
+               context = self.get_extra_context()
+               context.update({
                        'title': self.get_title(),
                        'url': self.get_url()
                })
+               return context
+       
+       def render(self):
+               t = self.get_template()
+               c = Context(self.get_context())
                return t.render(c)
        
        def __unicode__(self):
@@ -163,7 +175,7 @@ class BaseSearch(object):
                                        limit = self.result_limit
                                        if limit is not None:
                                                limit += 1
-                                       results = self.get_results(self.result_limit)
+                                       results = self.get_results(limit)
                                except:
                                        if settings.DEBUG:
                                                raise
@@ -202,18 +214,18 @@ class BaseSearch(object):
                raise NotImplementedError
        
        def get_result_querydict(self, result):
-               return make_tracking_querydict(self.search_arg, self.get_result_url(result))
+               url = self.get_result_url(result)
+               if url is None:
+                       return None
+               return make_tracking_querydict(self.search_arg, url)
        
        def get_result_template(self, result):
                if hasattr(self, 'result_template'):
                        return loader.get_template(self.result_template)
                if not hasattr(self, '_result_template'):
-                       self._result_template = Template(DEFAULT_RESULT_TEMPLATE_STRING)
+                       self._result_template = DEFAULT_RESULT_TEMPLATE
                return self._result_template
        
-       def get_ajax_result_template(self, result):
-               return getattr(self, 'ajax_result_template', DEFAULT_RESULT_TEMPLATE_STRING)
-       
        def get_result_extra_context(self, result):
                return {}
        
@@ -240,9 +252,6 @@ class BaseSearch(object):
 class DatabaseSearch(BaseSearch):
        model = None
        
-       def has_more_results(self):
-               return self.get_queryset().count() > self.result_limit
-       
        def search(self, limit=None):
                if not hasattr(self, '_qs'):
                        self._qs = self.get_queryset()
@@ -291,10 +300,21 @@ class JSONSearch(URLSearch):
 
 class GoogleSearch(JSONSearch):
        search_url = "http://ajax.googleapis.com/ajax/services/search/web"
-       query_format_str = "?v=1.0&q=%s"
        # TODO: Change this template to reflect the app's actual name.
        result_template = 'search/googlesearch.html'
-       timeout = 60
+       _cache_timeout = 60
+       verbose_name = "Google search (current site)"
+       
+       @property
+       def query_format_str(self):
+               default_args = self.default_args
+               if default_args:
+                       default_args += " "
+               return "?v=1.0&q=%s%%s" % urlquote_plus(default_args).replace('%', '%%')
+       
+       @property
+       def default_args(self):
+               return "site:%s" % Site.objects.get_current().domain
        
        def parse_response(self, response, limit=None):
                responseData = json.loads(response.read())['responseData']
@@ -357,7 +377,7 @@ else:
                def parse_response(self, response, limit=None):
                        strainer = self.strainer
                        soup = BeautifulSoup(response, parseOnlyThese=strainer)
-                       return self.parse_results(soup[:limit])
+                       return self.parse_results(soup.findAll(recursive=False, limit=limit))
                
                def parse_results(self, results):
                        """
@@ -374,5 +394,5 @@ else:
                
                def parse_response(self, response, limit=None):
                        strainer = self.strainer
-                       soup = BeautifulStoneSoup(page, selfClosingTags=self._self_closing_tags, parseOnlyThese=strainer)
-                       return self.parse_results(soup[:limit])
\ No newline at end of file
+                       soup = BeautifulStoneSoup(response, selfClosingTags=self._self_closing_tags, parseOnlyThese=strainer)
+                       return self.parse_results(soup.findAll(recursive=False, limit=limit))
\ No newline at end of file