def _process_results(self, raw_results, highlight=False): from haystack import site results = [] hits = raw_results.hits facets = {} spelling_suggestion = None if hasattr(raw_results, 'facets'): facets = { 'fields': raw_results.facets.get('facet_fields', {}), 'dates': raw_results.facets.get('facet_dates', {}), 'queries': raw_results.facets.get('facet_queries', {}), } for key in ['fields']: for facet_field in facets[key]: # Convert to a two-tuple, as Solr's json format returns a list of # pairs. facets[key][facet_field] = zip(facets[key][facet_field][::2], facets[key][facet_field][1::2]) if getattr(settings, 'HAYSTACK_INCLUDE_SPELLING', False) is True: if hasattr(raw_results, 'spellcheck'): if len(raw_results.spellcheck.get('suggestions', [])): # For some reason, it's an array of pairs. Pull off the # collated result from the end. spelling_suggestion = raw_results.spellcheck.get('suggestions')[-1] indexed_models = site.get_indexed_models() for raw_result in raw_results.docs: app_label, model_name = raw_result['django_ct'].split('.') additional_fields = {} for key, value in raw_result.items(): additional_fields[str(key)] = self.conn._to_python(value) del(additional_fields['django_ct']) del(additional_fields['django_id']) del(additional_fields['score']) if raw_result['id'] in getattr(raw_results, 'highlighting', {}): additional_fields['highlighted'] = raw_results.highlighting[raw_result['id']] model = get_model(app_label, model_name) if model: if model in indexed_models: result = SearchResult(app_label, model_name, raw_result['django_id'], raw_result['score'], **additional_fields) results.append(result) else: hits -= 1 else: hits -= 1 return { 'results': results, 'hits': hits, 'facets': facets, 'spelling_suggestion': spelling_suggestion, }
def changelist_view(self, request, extra_context=None): if not self.has_change_permission(request, None): raise PermissionDenied if not SEARCH_VAR in request.GET: # Do the usual song and dance. return super(SearchModelAdmin, self).changelist_view(request, extra_context) # Do a search of just this model and populate a Changelist with the # returned bits. if not self.model in site.get_indexed_models(): # Oops. That model isn't being indexed. Return the usual # behavior instead. return super(SearchModelAdmin, self).changelist_view(request, extra_context) # So. Much. Boilerplate. # Why copy-paste a few lines when you can copy-paste TONS of lines? list_display = list(self.list_display) changelist = SearchChangeList(request, self.model, list_display, self.list_display_links, self.list_filter, self.date_hierarchy, self.search_fields, self.list_select_related, self.list_per_page, self.list_editable, self) formset = changelist.formset = None media = self.media # Build the action form and populate it with available actions. # Check actions to see if any are available on this changelist actions = self.get_actions(request) if actions: action_form = self.action_form(auto_id=None) action_form.fields['action'].choices = self.get_action_choices(request) else: action_form = None selection_note = ungettext('0 of %(count)d selected', 'of %(count)d selected', len(changelist.result_list)) selection_note_all = ungettext('%(total_count)s selected', 'All %(total_count)s selected', changelist.result_count) context = { 'module_name': force_unicode(self.model._meta.verbose_name_plural), 'selection_note': selection_note % {'count': len(changelist.result_list)}, 'selection_note_all': selection_note_all % {'total_count': changelist.result_count}, 'title': changelist.title, 'is_popup': changelist.is_popup, 'cl': changelist, 'media': media, 'has_add_permission': self.has_add_permission(request), 'root_path': self.admin_site.root_path, 'app_label': self.model._meta.app_label, 'action_form': action_form, 'actions_on_top': self.actions_on_top, 'actions_on_bottom': self.actions_on_bottom, 'actions_selection_counter': getattr(self, 'actions_selection_counter', 0), } context.update(extra_context or {}) context_instance = template.RequestContext(request, current_app=self.admin_site.name) return render_to_response(self.change_list_template or [ 'admin/%s/%s/change_list.html' % (self.model._meta.app_label, self.model._meta.object_name.lower()), 'admin/%s/change_list.html' % self.model._meta.app_label, 'admin/change_list.html' ], context, context_instance=context_instance)
def search(self, query_string, sort_by=None, start_offset=0, end_offset=None, fields='', highlight=False, facets=None, date_facets=None, query_facets=None, narrow_queries=None, spelling_query=None, limit_to_registered_models=None, **kwargs): from haystack import site results = [] hits = len(self.mock_search_results) indexed_models = site.get_indexed_models() sliced = self.mock_search_results for result in sliced: model = get_model('core', self.model_name) if model: if model in indexed_models: results.append(result) else: hits -= 1 else: hits -= 1 return { 'results': results[start_offset:end_offset], 'hits': hits, }
def test_registrations(self): from haystack import backend sb = backend.SearchBackend() self.assertEqual(len(sb.site.get_indexed_models()), 2) from haystack import site self.assertEqual(len(site.get_indexed_models()), 2)
def _process_results(self, raw_results, highlight=False, query_string=''): from haystack import site results = [] hits = len(raw_results) facets = {} spelling_suggestion = None indexed_models = site.get_indexed_models() for doc_offset, raw_result in enumerate(raw_results): raw_result = dict(raw_result) app_label, model_name = raw_result['django_ct'].split('.') additional_fields = {} for key, value in raw_result.items(): additional_fields[str(key)] = self._to_python(value) del(additional_fields['django_ct']) del(additional_fields['django_id']) if highlight: from whoosh import analysis from whoosh.highlight import highlight, ContextFragmenter, UppercaseFormatter sa = analysis.StemmingAnalyzer() terms = [term.replace('*', '') for term in query_string.split()] # DRL_FIXME: Highlighting doesn't seem to work properly in testing. additional_fields['highlighted'] = { self.content_field_name: [highlight(additional_fields.get(self.content_field_name), terms, sa, ContextFragmenter(terms), UppercaseFormatter())], } # Requires Whoosh 0.1.20+. if hasattr(raw_results, 'score'): score = raw_results.score(doc_offset) else: score = None if score is None: score = 0 model = get_model(app_label, model_name) if model: if model in indexed_models: result = SearchResult(app_label, model_name, raw_result['django_id'], score, **additional_fields) results.append(result) else: hits -= 1 else: hits -= 1 if getattr(settings, 'HAYSTACK_INCLUDE_SPELLING', False) is True: spelling_suggestion = self.create_spelling_suggestion(query_string) return { 'results': results, 'hits': hits, 'facets': facets, 'spelling_suggestion': spelling_suggestion, }
def handle_noargs(self, **options): """Provides feedback about the current Haystack setup.""" # Cause the default site to load. from haystack import site index_count = len(site.get_indexed_models()) print "Loaded URLconf to initialize SearchSite..." print "Main site registered %s index(es)." % index_count
def test_registrations(self): from haystack import backend sb = backend.SearchBackend() self.assertEqual(len(sb.site.get_indexed_models()), 2) from haystack import site self.assertEqual(len(site.get_indexed_models()), 2) from site_registration.models import Foo, Bar site.unregister(Bar) self.assertEqual(len(sb.site.get_indexed_models()), 1) self.assertEqual(len(site.get_indexed_models()), 1) site.unregister(Foo) self.assertEqual(len(sb.site.get_indexed_models()), 0) self.assertEqual(len(site.get_indexed_models()), 0)
def search(self, query, highlight=False): from haystack import site results = [] hits = len(MOCK_SEARCH_RESULTS) indexed_models = site.get_indexed_models() for result in MOCK_SEARCH_RESULTS: model = get_model('core', 'mockmodel') if model: if model in indexed_models: results.append(result) else: hits -= 1 else: hits -= 1 return { 'results': results, 'hits': hits, }
def search(self, query_string, sort_by=None, start_offset=0, end_offset=None, fields='', highlight=False, facets=None, date_facets=None, query_facets=None, narrow_queries=None, spelling_query=None, limit_to_registered_models=None, result_class=None, **kwargs): from haystack import site results = [] hits = len(self.mock_search_results) indexed_models = site.get_indexed_models() sliced = self.mock_search_results for result in sliced: model = get_model('core', self.model_name) if model: if model in indexed_models: results.append(result) else: hits -= 1 else: hits -= 1 return { 'results': results[start_offset:end_offset], 'hits': hits, }
def _process_results(self, raw_page, highlight=False, query_string='', spelling_query=None): from haystack import site results = [] # It's important to grab the hits first before slicing. Otherwise, this # can cause pagination failures. hits = len(raw_page) facets = {} spelling_suggestion = None indexed_models = site.get_indexed_models() for doc_offset, raw_result in enumerate(raw_page): score = raw_page.score(doc_offset) or 0 app_label, model_name = raw_result['django_ct'].split('.') additional_fields = {} model = get_model(app_label, model_name) if model and model in indexed_models: for key, value in raw_result.items(): index = site.get_index(model) string_key = str(key) if string_key in index.fields and hasattr(index.fields[string_key], 'convert'): # Special-cased due to the nature of KEYWORD fields. if isinstance(index.fields[string_key], MultiValueField): if value is None or len(value) is 0: additional_fields[string_key] = [] else: additional_fields[string_key] = value.split(',') else: additional_fields[string_key] = index.fields[string_key].convert(value) else: additional_fields[string_key] = self._to_python(value) del(additional_fields['django_ct']) del(additional_fields['django_id']) if highlight: from whoosh import analysis from whoosh.highlight import highlight, ContextFragmenter, UppercaseFormatter sa = analysis.StemmingAnalyzer() terms = [term.replace('*', '') for term in query_string.split()] additional_fields['highlighted'] = { self.content_field_name: [highlight(additional_fields.get(self.content_field_name), terms, sa, ContextFragmenter(terms), UppercaseFormatter())], } result = SearchResult(app_label, model_name, raw_result['django_id'], score, **additional_fields) results.append(result) else: hits -= 1 if getattr(settings, 'HAYSTACK_INCLUDE_SPELLING', False): if spelling_query: spelling_suggestion = self.create_spelling_suggestion(spelling_query) else: spelling_suggestion = self.create_spelling_suggestion(query_string) return { 'results': results, 'hits': hits, 'facets': facets, 'spelling_suggestion': spelling_suggestion, }
def _process_results( self, raw_results, start_offset, end_offset, highlight=False, query_string="", spelling_query=None ): from haystack import site results = [] # It's important to grab the hits first before slicing. Otherwise, this # can cause pagination failures. hits = len(raw_results) raw_results = raw_results[start_offset:end_offset] facets = {} spelling_suggestion = None indexed_models = site.get_indexed_models() for doc_offset, raw_result in enumerate(raw_results): raw_result = dict(raw_result) app_label, model_name = raw_result["django_ct"].split(".") additional_fields = {} model = get_model(app_label, model_name) if model and model in indexed_models: for key, value in raw_result.items(): index = site.get_index(model) string_key = str(key) if string_key in index.fields and hasattr(index.fields[string_key], "convert"): additional_fields[string_key] = index.fields[string_key].convert(value) else: additional_fields[string_key] = self._to_python(value) del (additional_fields["django_ct"]) del (additional_fields["django_id"]) if highlight: from whoosh import analysis from whoosh.highlight import highlight, ContextFragmenter, UppercaseFormatter sa = analysis.StemmingAnalyzer() terms = [term.replace("*", "") for term in query_string.split()] # DRL_FIXME: Highlighting doesn't seem to work properly in testing. additional_fields["highlighted"] = { self.content_field_name: [ highlight( additional_fields.get(self.content_field_name), terms, sa, ContextFragmenter(terms), UppercaseFormatter(), ) ] } # Requires Whoosh 0.1.20+. if hasattr(raw_results, "score"): score = raw_results.score(doc_offset) else: score = None if score is None: score = 0 result = SearchResult(app_label, model_name, raw_result["django_id"], score, **additional_fields) results.append(result) else: hits -= 1 if getattr(settings, "HAYSTACK_INCLUDE_SPELLING", False): if spelling_query: spelling_suggestion = self.create_spelling_suggestion(spelling_query) else: spelling_suggestion = self.create_spelling_suggestion(query_string) return {"results": results, "hits": hits, "facets": facets, "spelling_suggestion": spelling_suggestion}
def _process_results(self, raw_results, highlight=False, result_class=None): if not self.site: from haystack import site else: site = self.site results = [] hits = raw_results.hits facets = {} spelling_suggestion = None if result_class is None: result_class = SearchResult if hasattr(raw_results, 'facets'): facets = { 'fields': raw_results.facets.get('facet_fields', {}), 'dates': raw_results.facets.get('facet_dates', {}), 'queries': raw_results.facets.get('facet_queries', {}), } for key in ['fields']: for facet_field in facets[key]: # Convert to a two-tuple, as Solr's json format returns a list of # pairs. facets[key][facet_field] = zip( facets[key][facet_field][::2], facets[key][facet_field][1::2]) if getattr(settings, 'HAYSTACK_INCLUDE_SPELLING', False) is True: if hasattr(raw_results, 'spellcheck'): if len(raw_results.spellcheck.get('suggestions', [])): # For some reason, it's an array of pairs. Pull off the # collated result from the end. spelling_suggestion = raw_results.spellcheck.get( 'suggestions')[-1] indexed_models = site.get_indexed_models() for raw_result in raw_results.docs: app_label, model_name = raw_result[DJANGO_CT].split('.') additional_fields = {} model = get_model(app_label, model_name) if model and model in indexed_models: for key, value in raw_result.items(): index = site.get_index(model) string_key = str(key) if string_key in index.fields and hasattr( index.fields[string_key], 'convert'): additional_fields[string_key] = index.fields[ string_key].convert(value) else: additional_fields[string_key] = self.conn._to_python( value) del (additional_fields[DJANGO_CT]) del (additional_fields[DJANGO_ID]) del (additional_fields['score']) if raw_result[ID] in getattr(raw_results, 'highlighting', {}): additional_fields[ 'highlighted'] = raw_results.highlighting[ raw_result[ID]] result = result_class(app_label, model_name, raw_result[DJANGO_ID], raw_result['score'], searchsite=self.site, **additional_fields) results.append(result) else: hits -= 1 return { 'results': results, 'hits': hits, 'facets': facets, 'spelling_suggestion': spelling_suggestion, }
def changelist_view(self, request, extra_context=None): if not self.has_change_permission(request, None): raise PermissionDenied if not SEARCH_VAR in request.GET: # Do the usual song and dance. return super(SearchModelAdmin, self).changelist_view(request, extra_context) # Do a search of just this model and populate a Changelist with the # returned bits. if not self.model in site.get_indexed_models(): # Oops. That model isn't being indexed. Return the usual # behavior instead. return super(SearchModelAdmin, self).changelist_view(request, extra_context) # So. Much. Boilerplate. # Why copy-paste a few lines when you can copy-paste TONS of lines? list_display = list(self.list_display) changelist = SearchChangeList( request, self.model, list_display, self.list_display_links, self.list_filter, self.date_hierarchy, self.search_fields, self.list_select_related, self.list_per_page, self.list_editable, self) formset = changelist.formset = None media = self.media # Build the action form and populate it with available actions. # Check actions to see if any are available on this changelist actions = self.get_actions(request) if actions: action_form = self.action_form(auto_id=None) action_form.fields['action'].choices = self.get_action_choices( request) else: action_form = None selection_note = ungettext('0 of %(count)d selected', 'of %(count)d selected', len(changelist.result_list)) selection_note_all = ungettext('%(total_count)s selected', 'All %(total_count)s selected', changelist.result_count) context = { 'module_name': force_unicode(self.model._meta.verbose_name_plural), 'selection_note': selection_note % { 'count': len(changelist.result_list) }, 'selection_note_all': selection_note_all % { 'total_count': changelist.result_count }, 'title': changelist.title, 'is_popup': changelist.is_popup, 'cl': changelist, 'media': media, 'has_add_permission': self.has_add_permission(request), 'root_path': self.admin_site.root_path, 'app_label': self.model._meta.app_label, 'action_form': action_form, 'actions_on_top': self.actions_on_top, 'actions_on_bottom': self.actions_on_bottom, 'actions_selection_counter': getattr(self, 'actions_selection_counter', 0), } context.update(extra_context or {}) context_instance = template.RequestContext( request, current_app=self.admin_site.name) return render_to_response(self.change_list_template or [ 'admin/%s/%s/change_list.html' % (self.model._meta.app_label, self.model._meta.object_name.lower()), 'admin/%s/change_list.html' % self.model._meta.app_label, 'admin/change_list.html' ], context, context_instance=context_instance)
def _process_results(self, raw_page, highlight=False, query_string="", spelling_query=None, result_class=None): from haystack import site results = [] # It's important to grab the hits first before slicing. Otherwise, this # can cause pagination failures. hits = len(raw_page) if result_class is None: result_class = SearchResult facets = {} spelling_suggestion = None indexed_models = site.get_indexed_models() for doc_offset, raw_result in enumerate(raw_page): score = raw_page.score(doc_offset) or 0 app_label, model_name = raw_result[DJANGO_CT].split(".") additional_fields = {} model = get_model(app_label, model_name) if model and model in indexed_models: for key, value in raw_result.items(): index = site.get_index(model) string_key = str(key) if string_key in index.fields and hasattr(index.fields[string_key], "convert"): # Special-cased due to the nature of KEYWORD fields. if index.fields[string_key].is_multivalued: if value is None or len(value) is 0: additional_fields[string_key] = [] else: additional_fields[string_key] = value.split(",") else: additional_fields[string_key] = index.fields[string_key].convert(value) else: additional_fields[string_key] = self._to_python(value) del (additional_fields[DJANGO_CT]) del (additional_fields[DJANGO_ID]) if highlight: from whoosh import analysis from whoosh.highlight import highlight, ContextFragmenter, UppercaseFormatter sa = analysis.StemmingAnalyzer() terms = [term.replace("*", "") for term in query_string.split()] additional_fields["highlighted"] = { self.content_field_name: [ highlight( additional_fields.get(self.content_field_name), terms, sa, ContextFragmenter(terms), UppercaseFormatter(), ) ] } result = result_class(app_label, model_name, raw_result[DJANGO_ID], score, **additional_fields) results.append(result) else: hits -= 1 if getattr(settings, "HAYSTACK_INCLUDE_SPELLING", False): if spelling_query: spelling_suggestion = self.create_spelling_suggestion(spelling_query) else: spelling_suggestion = self.create_spelling_suggestion(query_string) return {"results": results, "hits": hits, "facets": facets, "spelling_suggestion": spelling_suggestion}
def _process_results(self, raw_results, highlight=False, result_class=None): if not self.site: from haystack import site else: site = self.site results = [] hits = raw_results.hits facets = {} spelling_suggestion = None if result_class is None: result_class = SearchResult if hasattr(raw_results, "facets"): facets = { "fields": raw_results.facets.get("facet_fields", {}), "dates": raw_results.facets.get("facet_dates", {}), "queries": raw_results.facets.get("facet_queries", {}), } for key in ["fields"]: for facet_field in facets[key]: # Convert to a two-tuple, as Solr's json format returns a list of # pairs. facets[key][facet_field] = zip(facets[key][facet_field][::2], facets[key][facet_field][1::2]) if getattr(settings, "HAYSTACK_INCLUDE_SPELLING", False) is True: if hasattr(raw_results, "spellcheck"): if len(raw_results.spellcheck.get("suggestions", [])): # For some reason, it's an array of pairs. Pull off the # collated result from the end. spelling_suggestion = raw_results.spellcheck.get("suggestions")[-1] indexed_models = site.get_indexed_models() for raw_result in raw_results.docs: app_label, model_name = raw_result[DJANGO_CT].split(".") additional_fields = {} model = get_model(app_label, model_name) if model and model in indexed_models: for key, value in raw_result.items(): index = site.get_index(model) string_key = str(key) if string_key in index.fields and hasattr(index.fields[string_key], "convert"): additional_fields[string_key] = index.fields[string_key].convert(value) else: additional_fields[string_key] = self.conn._to_python(value) del (additional_fields[DJANGO_CT]) del (additional_fields[DJANGO_ID]) del (additional_fields["score"]) if raw_result[ID] in getattr(raw_results, "highlighting", {}): additional_fields["highlighted"] = raw_results.highlighting[raw_result[ID]] result = result_class( app_label, model_name, raw_result[DJANGO_ID], raw_result["score"], searchsite=self.site, **additional_fields ) results.append(result) else: hits -= 1 return {"results": results, "hits": hits, "facets": facets, "spelling_suggestion": spelling_suggestion}
return prepare_date(obj.ctime) def prepare_mtime(self, obj): return prepare_date(obj.mtime) def prepare_description(self, obj): return plaintext(obj.description, obj) rendered = CharField(use_template=True, indexed=False) rendered_add = CharField(use_template=True, indexed=False) set_template_name(GroupIndex) site.register(models.GroupInfo, GroupIndex) indexed = site.get_indexed_models() def get_state_class(obj): if obj.is_cancelled: cls = "cancelled" elif obj.is_official: cls = "official" elif obj.is_draft: cls = "draft" elif obj.is_deprecated: cls = "deprecated" else: cls = "proposed" return "state-" + cls