import datetime
+import itertools
from django.conf import settings
from django.conf.urls.defaults import patterns, url
from philo.contrib.sobol import registry
from philo.contrib.sobol.forms import SearchForm
-from philo.contrib.sobol.utils import HASH_REDIRECT_GET_KEY, URL_REDIRECT_GET_KEY, SEARCH_ARG_GET_KEY, check_redirect_hash
+from philo.contrib.sobol.utils import HASH_REDIRECT_GET_KEY, URL_REDIRECT_GET_KEY, SEARCH_ARG_GET_KEY, check_redirect_hash, RegistryIterator
from philo.exceptions import ViewCanNotProvideSubpath
from philo.models import MultiView, Page
from philo.models.fields import SlugMultipleChoiceField
get_latest_by = 'datetime'
+class RegistryChoiceField(SlugMultipleChoiceField):
+ def _get_choices(self):
+ if isinstance(self._choices, RegistryIterator):
+ return self._choices.copy()
+ elif hasattr(self._choices, 'next'):
+ choices, self._choices = itertools.tee(self._choices)
+ return choices
+ else:
+ return self._choices
+ choices = property(_get_choices)
+
+
+try:
+ from south.modelsinspector import add_introspection_rules
+except ImportError:
+ pass
+else:
+ add_introspection_rules([], ["^philo\.contrib\.shipherd\.models\.RegistryChoiceField"])
+
+
class SearchView(MultiView):
results_page = models.ForeignKey(Page, related_name='search_results_related')
- searches = SlugMultipleChoiceField(choices=registry.iterchoices())
+ searches = RegistryChoiceField(choices=registry.iterchoices())
enable_ajax_api = models.BooleanField("Enable AJAX API", default=True, help_text="Search results will be available <i>only</i> by AJAX, not as template variables.")
placeholder_text = models.CharField(max_length=75, default="Search")
from django.utils.text import capfirst
from django.template import loader, Context, Template
-from philo.contrib.sobol.utils import make_tracking_querydict
+from philo.contrib.sobol.utils import make_tracking_querydict, RegistryIterator
if getattr(settings, 'SOBOL_USE_EVENTLET', False):
__all__ = (
- 'Result', 'BaseSearch', 'DatabaseSearch', 'URLSearch', 'JSONSearch', 'GoogleSearch', 'registry'
+ 'Result', 'BaseSearch', 'DatabaseSearch', 'URLSearch', 'JSONSearch', 'GoogleSearch', 'SearchRegistry', 'registry'
)
class SearchRegistry(object):
- # Holds a registry of search types by slug.
+ """Holds a registry of search types by slug."""
+
def __init__(self):
self._registry = {}
return self._registry.items()
def iteritems(self):
- return self._registry.iteritems()
+ return RegistryIterator(self._registry, 'iteritems')
def iterchoices(self):
- for slug, search in self.iteritems():
- yield slug, search.verbose_name
+ return RegistryIterator(self._registry, 'iteritems', lambda x: (x[0], x[1].verbose_name))
def __getitem__(self, key):
return self._registry[key]
class BaseSearchMetaclass(type):
def __new__(cls, name, bases, attrs):
if 'verbose_name' not in attrs:
- attrs['verbose_name'] = capfirst(convert_camelcase(name))
+ attrs['verbose_name'] = capfirst(' '.join(convert_camelcase(name).rsplit(' ', 1)[:-1]))
if 'slug' not in attrs:
attrs['slug'] = name.lower()
return super(BaseSearchMetaclass, cls).__new__(cls, name, bases, attrs)
return make_tracking_querydict(self.search_arg, self.more_results_url)
def __unicode__(self):
- return ' '.join(self.__class__.verbose_name.rsplit(' ', 1)[:-1]) + ' results'
+ return self.verbose_name
class DatabaseSearch(BaseSearch):
SEARCH_ARG_GET_KEY, urlquote_plus(search_arg),
URL_REDIRECT_GET_KEY, urlquote(url),
HASH_REDIRECT_GET_KEY, make_redirect_hash(search_arg, url))
- )
\ No newline at end of file
+ )
+
+
+class RegistryIterator(object):
+ def __init__(self, registry, iterattr='__iter__', transform=lambda x:x):
+ if not hasattr(registry, iterattr):
+ raise AttributeError("Registry has no attribute %s" % iterattr)
+ self.registry = registry
+ self.iterattr = iterattr
+ self.transform = transform
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ if not hasattr(self, '_iter'):
+ self._iter = getattr(self.registry, self.iterattr)()
+
+ return self.transform(self._iter.next())
+
+ def copy(self):
+ return self.__class__(self.registry, self.iterattr, self.transform)
\ No newline at end of file