Implemented more robust delayed registry iteration. Modules declaring new searches...
[philo.git] / philo / contrib / sobol / models.py
index 2cb1651..cd773a5 100644 (file)
@@ -1,9 +1,11 @@
 import datetime
 import datetime
+import itertools
 
 from django.conf import settings
 from django.conf.urls.defaults import patterns, url
 from django.contrib import messages
 from django.core.exceptions import ValidationError
 
 from django.conf import settings
 from django.conf.urls.defaults import patterns, url
 from django.contrib import messages
 from django.core.exceptions import ValidationError
+from django.core.validators import URLValidator
 from django.db import models
 from django.http import HttpResponseRedirect, Http404, HttpResponse
 from django.utils import simplejson as json
 from django.db import models
 from django.http import HttpResponseRedirect, Http404, HttpResponse
 from django.utils import simplejson as json
@@ -11,11 +13,10 @@ from django.utils.datastructures import SortedDict
 
 from philo.contrib.sobol import registry
 from philo.contrib.sobol.forms import SearchForm
 
 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
 from philo.exceptions import ViewCanNotProvideSubpath
 from philo.models import MultiView, Page
 from philo.models.fields import SlugMultipleChoiceField
-from philo.validators import RedirectValidator
 
 eventlet = None
 if getattr(settings, 'SOBOL_USE_EVENTLET', False):
 
 eventlet = None
 if getattr(settings, 'SOBOL_USE_EVENTLET', False):
@@ -83,7 +84,7 @@ class Search(models.Model):
 
 class ResultURL(models.Model):
        search = models.ForeignKey(Search, related_name='result_urls')
 
 class ResultURL(models.Model):
        search = models.ForeignKey(Search, related_name='result_urls')
-       url = models.TextField(validators=[RedirectValidator()])
+       url = models.TextField(validators=[URLValidator()])
        
        def __unicode__(self):
                return self.url
        
        def __unicode__(self):
                return self.url
@@ -133,9 +134,29 @@ class Click(models.Model):
                get_latest_by = 'datetime'
 
 
                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')
 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")
        
        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")
        
@@ -204,7 +225,7 @@ class SearchView(MultiView):
                                        })
                                else:
                                        context.update({
                                        })
                                else:
                                        context.update({
-                                               'searches': [{'verbose_name': verbose_name, 'slug': slug, 'url': self.reverse('ajax_api_view', kwargs={'slug': slug}, node=request.node), 'result_template': registry[slug].result_template} for slug, verbose_name in registry.iterchoices() if slug in self.searches]
+                                               'searches': [{'verbose_name': verbose_name, 'slug': slug, 'url': "%s?%s=%s" % (self.reverse('ajax_api_view', kwargs={'slug': slug}, node=request.node), SEARCH_ARG_GET_KEY, search_string), 'result_template': registry[slug].result_template} for slug, verbose_name in registry.iterchoices() if slug in self.searches]
                                        })
                else:
                        form = SearchForm()
                                        })
                else:
                        form = SearchForm()
@@ -224,7 +245,8 @@ class SearchView(MultiView):
                        raise Http404
                
                search_instance = self.get_search_instance(slug, search_string)
                        raise Http404
                
                search_instance = self.get_search_instance(slug, search_string)
-               response = HttpResponse(json.dumps({
+               
+               return HttpResponse(json.dumps({
                        'results': [result.get_context() for result in search_instance.results],
                        'results': [result.get_context() for result in search_instance.results],
-               }))
-               return response
\ No newline at end of file
+                       'rendered': [result.render() for result in search_instance.results]
+               }))
\ No newline at end of file