search_instances = []
for slug in self.searches:
- search_instance = get_search_instance(slug, search_string)
- search_instances.append(search_instance)
+ if slug in registry:
+ search_instance = get_search_instance(slug, search_string)
+ search_instances.append(search_instance)
- if self.enable_ajax_api:
- search_instance.ajax_api_url = "%s?%s=%s" % (self.reverse('ajax_api_view', kwargs={'slug': slug}, node=request.node), SEARCH_ARG_GET_KEY, search_string)
+ if self.enable_ajax_api:
+ search_instance.ajax_api_url = "%s?%s=%s" % (self.reverse('ajax_api_view', kwargs={'slug': slug}, node=request.node), SEARCH_ARG_GET_KEY, search_string)
if eventlet and not self.enable_ajax_api:
pool = eventlet.GreenPool()
"""
search_string = request.GET.get(SEARCH_ARG_GET_KEY)
- if not request.is_ajax() or not self.enable_ajax_api or slug not in self.searches or search_string is None:
+ if not request.is_ajax() or not self.enable_ajax_api or slug not in registry or slug not in self.searches or search_string is None:
raise Http404
search_instance = get_search_instance(slug, search_string)
return HttpResponse(json.dumps({
- 'results': [result.get_context() for result in search_instance.results],
- 'rendered': [result.render() for result in search_instance.results],
- 'hasMoreResults': search.has_more_results(),
- 'moreResultsURL': (u"?%s" % search.more_results_querydict.urlencode()) if search.more_results_querydict else None,
+ 'results': [result.render() for result in search_instance.results],
+ 'hasMoreResults': search_instance.has_more_results,
+ 'moreResultsURL': (u"?%s" % search_instance.more_results_querydict.urlencode()) if search_instance.more_results_querydict else None,
}), mimetype="application/json")
\ No newline at end of file
if 'verbose_name' not in attrs:
attrs['verbose_name'] = capfirst(' '.join(convert_camelcase(name).rsplit(' ', 1)[:-1]))
if 'slug' not in attrs:
- attrs['slug'] = name.lower()
+ attrs['slug'] = name[:-6].lower() if name.endswith("Search") else name.lower()
return super(BaseSearchMetaclass, cls).__new__(cls, name, bases, attrs)
"""
__metaclass__ = BaseSearchMetaclass
- #: The number of results to return from the complete list. Default: 10
- result_limit = 10
+ #: The number of results to return from the complete list. Default: 5
+ result_limit = 5
#: How long the items for the search should be cached (in minutes). Default: 48 hours.
_cache_timeout = 60*48
#: The path to the template which will be used to render the :class:`Result`\ s for this search.
"""Returns any extra context to be used when rendering the ``result``."""
return {}
+ @property
def has_more_results(self):
"""Returns ``True`` if there are more results than :attr:`result_limit` and ``False`` otherwise."""
return len(self.results) > self.result_limit
@property
def more_results_url(self):
- """Returns the actual url for more results. This should be accessed through :attr:`more_results_querydict` in the template so that the click can be tracked."""
- raise NotImplementedError
+ """Returns the actual url for more results. This should be accessed through :attr:`more_results_querydict` in the template so that the click can be tracked. By default, simply returns ``None``."""
+ return None
@property
def more_results_querydict(self):
"""Returns a :class:`QueryDict` for tracking whether people click on a 'more results' link."""
- return make_tracking_querydict(self.search_arg, self.more_results_url)
+ url = self.more_results_url
+ if url:
+ return make_tracking_querydict(self.search_arg, url)
+ return None
def __unicode__(self):
return self.verbose_name
_cache_timeout = 60
verbose_name = "Google search (current site)"
result_template = "sobol/search/googlesearch.html"
+ _more_results_url = None
@property
def query_format_str(self):
--- /dev/null
+(function($){
+ var sobol = window.sobol = {}
+ sobol.setup = function(){
+ var searches = sobol.searches = $('article.search');
+ for (i=0;i<searches.length;i++) {
+ (function(){
+ var s = searches[i];
+ $.ajax({
+ url: s.getAttribute('data-url'),
+ dataType: 'json',
+ success: function(data){
+ $(s).removeClass('loading')
+ if (data['results'].length) {
+ s.innerHTML += "<dl>" + data['results'].join("") + "</dl>";
+ if(data['hasMoreResults'] && data['moreResultsURL']) s.innerHTML += "<footer><p><a href='" + data['moreResultsURL'] + "'>See more results</a></p></footer>";
+ } else {
+ $(s).addClass('empty')
+ s.innerHTML += "<p>No results found.</p>"
+ }
+ },
+ error: function(data, textStatus, errorThrown){
+ $(s).removeClass('loading');
+ text = errorThrown ? errorThrown : textStatus ? textStatus : "Error occurred."
+ if (errorThrown) {
+ s.innerHTML += "<p>" + errorThrown + "</p>"
+ };
+ }
+ });
+ }());
+ };
+ };
+ $(sobol.setup);
+}(jQuery));
\ No newline at end of file
--- /dev/null
+{% with node.view.enable_ajax_api as ajax %}
+{% if ajax %}<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script><script type="text/javascript" src="{{ STATIC_URL }}sobol/ajax_search.js"></script>{% endif %}
+{% for search in searches %}
+<article {% if ajax %}class="search loading {{ search.slug }}" data-url="{{ search.ajax_api_url }}" data-title="{{ search }}"{% else %}class="search {{ search.slug }}"{% endif %}>
+ <header>
+ <a name='{{ search.slug }}'></a>
+ <h1>{{ search }}</h1>
+ </header>
+ {% if not ajax %}
+ <dl>
+ {% for result in search.results %}
+ {{ result }}
+ {% endfor %}
+ </dl>
+ {% if search.has_more_results and search.more_results_url %}
+ <footer>
+ <p><a href="?{{ search.more_results_querydict.urlencode }}">See more results</a></p>
+ </footer>
+ {% endif %}
+ {% endif %}
+</article>
+{% endfor %}
+{% endwith %}
\ No newline at end of file
-{% if url %}<a href='{{ url }}'>{% endif %}{{ title }}{% if url %}</a>{% endif %}
\ No newline at end of file
+<dt>{% if url %}<a href='{{ url }}'>{% endif %}{{ title }}{% if url %}</a>{% endif %}</dt>
\ No newline at end of file
-<article>
- <h1><a href="{{ url }}">{{ title|safe }}</a></h1>
- <p>{{ content|safe }}</p>
-</article>
\ No newline at end of file
+<dt><a href="{{ url }}">{{ title|safe }}</a></dt>
+<dd>{{ result.content|safe }}</dd>
\ No newline at end of file