From: Joseph Spiros Date: Wed, 13 Apr 2011 20:29:29 +0000 (-0400) Subject: Merge branch 'master' of git://github.com/melinath/philo X-Git-Tag: philo-0.9~15 X-Git-Url: http://git.ithinksw.org/philo.git/commitdiff_plain/8a7ab75997519a2e99d8a1bf7218af016eaf187d?hp=a917b5dd29218812c04a6eb8e89d21f17324553d Merge branch 'master' of git://github.com/melinath/philo * 'master' of git://github.com/melinath/philo: Added 1.2.X compatibility to shipherd LazyNavigationRecurser. Minor tweaks to sobol result handling. Minor corrections and improvements to sobol. Added crude double-import detection to search registration. Added Django 1.2 fallback to SlugMultipleChoiceField formfield method. Fixed a sobol bug which was causing search views to always use all available searches. Added some help text to the ajax api boolean. Modified the get_start and get_end methods to return datetimes if times are specified. --- diff --git a/contrib/julian/models.py b/contrib/julian/models.py index 5dea7a3..5c49c7e 100644 --- a/contrib/julian/models.py +++ b/contrib/julian/models.py @@ -79,10 +79,10 @@ class TimedModel(models.Model): raise ValidationError("A %s cannot end before it starts." % self.__class__.__name__) def get_start(self): - return self.start_date + return datetime.datetime.combine(self.start_date, self.start_time) if self.start_time else self.start_date def get_end(self): - return self.end_date + return datetime.datetime.combine(self.end_date, self.end_time) if self.end_time else self.end_date class Meta: abstract = True diff --git a/contrib/shipherd/templatetags/shipherd.py b/contrib/shipherd/templatetags/shipherd.py index 1413bdf..6e36126 100644 --- a/contrib/shipherd/templatetags/shipherd.py +++ b/contrib/shipherd/templatetags/shipherd.py @@ -1,4 +1,4 @@ -from django import template +from django import template, VERSION as django_version from django.conf import settings from django.utils.safestring import mark_safe from philo.contrib.shipherd.models import Navigation @@ -60,6 +60,10 @@ class LazyNavigationRecurser(object): context['item'] = item context['children'] = self.__class__(self.template_nodes, item.get_children(), context, request) + # Django 1.2.X compatibility - a lazy recurser will not be called if accessed as a template variable. + if django_version < (1,3): + context['children'] = context['children']() + # Then render the nodelist bit by bit. for node in self.template_nodes: bits.append(node.render(context)) diff --git a/contrib/sobol/models.py b/contrib/sobol/models.py index b653c09..e4e4202 100644 --- a/contrib/sobol/models.py +++ b/contrib/sobol/models.py @@ -130,13 +130,13 @@ class Click(models.Model): class SearchView(MultiView): results_page = models.ForeignKey(Page, related_name='search_results_related') searches = SlugMultipleChoiceField(choices=registry.iterchoices()) - enable_ajax_api = models.BooleanField("Enable AJAX API", default=True) + enable_ajax_api = models.BooleanField("Enable AJAX API", default=True, help_text="Search results will be available only by AJAX, not as template variables.") placeholder_text = models.CharField(max_length=75, default="Search") search_form = SearchForm def __unicode__(self): - return u"%s (%s)" % (self.placeholder_text, u", ".join([display for slug, display in registry.iterchoices()])) + return u"%s (%s)" % (self.placeholder_text, u", ".join([display for slug, display in registry.iterchoices() if slug in self.searches])) def get_reverse_params(self, obj): raise ViewCanNotProvideSubpath @@ -198,7 +198,7 @@ class SearchView(MultiView): }) else: context.update({ - 'searches': [{'verbose_name': verbose_name, 'url': self.reverse('ajax_api_view', kwargs={'slug': slug}, node=request.node)} for slug, verbose_name in registry.iterchoices()] + 'searches': [{'verbose_name': verbose_name, 'url': self.reverse('ajax_api_view', kwargs={'slug': slug}, node=request.node)} for slug, verbose_name in registry.iterchoices() if slug in self.searches] }) else: form = SearchForm() diff --git a/contrib/sobol/search.py b/contrib/sobol/search.py index 36c2b5d..8c695c6 100644 --- a/contrib/sobol/search.py +++ b/contrib/sobol/search.py @@ -25,9 +25,10 @@ __all__ = ( SEARCH_CACHE_KEY = 'philo_sobol_search_results' DEFAULT_RESULT_TEMPLATE_STRING = "{% if url %}{% endif %}{{ title }}{% if url %}{% 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 @@ -93,7 +95,10 @@ class Result(object): return self.search.get_result_title(self.result) def get_url(self): - return "?%s" % 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) @@ -170,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 @@ -209,13 +214,16 @@ 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_result_extra_context(self, result): @@ -244,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() @@ -298,7 +303,7 @@ class GoogleSearch(JSONSearch): 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 def parse_response(self, response, limit=None): responseData = json.loads(response.read())['responseData'] @@ -361,7 +366,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): """ @@ -378,5 +383,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 diff --git a/models/fields/__init__.py b/models/fields/__init__.py index 1f9603e..d900e31 100644 --- a/models/fields/__init__.py +++ b/models/fields/__init__.py @@ -109,7 +109,8 @@ class SlugMultipleChoiceField(models.Field): del kwargs[k] defaults.update(kwargs) - form_class = forms.TypedMultipleChoiceField + # Django 1.2 does not supply MultipleChoiceField + form_class = getattr(forms, 'TypedMultipleChoiceField', forms.MultipleChoiceField) return form_class(**defaults) def validate(self, value, model_instance):