def __init__(self, *args, **kwargs): """ If we're in a recognised faceting engine, display and allow faceting. """ super(PreSelectedModelSearchForm, self).__init__(*args, **kwargs) if 'models' in self.fields: self.fields['models'].initial = [x[0] for x in model_choices()] self.fields['models'].label = _("Only models") self.haystack_config = HaystackConfig() self.fields['content_field'].choices = content_field_choices() self.version = self.haystack_config.version if self.should_allow_faceting(): possible_facets = self.configure_faceting() self.fields['possible_facets'].choices = possible_facets self.fields['selected_facets'] = SelectedFacetsField( choices=(), required=False, possible_facets=possible_facets) if self.has_multiple_connections(): wtf = self.get_possible_connections() self.fields['connection'].choices = tuple(wtf) # noqa self.fields['connection'].initial = 'default' else: self.fields['connection'].widget = HiddenInput()
def test_get_valid_filters_version2(): conf = HaystackConfig() filters = tuple((x, force_text(y)) for x, y in conf.get_valid_filters()) assert filters == (('exact', 'exact'), ('gt', 'greater than'), ('gte', 'greater than or equal to'), ('in', 'in'), ('lt', 'less than'), ('lte', 'less than or equal to'), ('range', 'range (inclusive)'), ('startswith', 'starts with'))
class PreSelectedModelSearchForm(ModelSearchForm): possible_facets = MultipleChoiceField(widget=CheckboxSelectMultiple, choices=(), required=False, label=_("Finding facets on")) search_type = ChoiceField(choices=[(0, "Autoquery"), (1, "Exact")], required=False, initial=0, label=_("Search type")) content_field = ChoiceField(choices=(), required=False, label=_("Indexed fields")) connection = ChoiceField(choices=(), required=False) p = IntegerField(required=False, label=_("Page"), min_value=0, max_value=99999999, initial=1) def __init__(self, *args, **kwargs): """ If we're in a recognised faceting engine, display and allow faceting. """ super(PreSelectedModelSearchForm, self).__init__(*args, **kwargs) if 'models' in self.fields: self.fields['models'].initial = [x[0] for x in model_choices()] self.fields['models'].label = _("Only models") self.haystack_config = HaystackConfig() self.fields['content_field'].choices = content_field_choices() self.version = self.haystack_config.version if self.should_allow_faceting(): possible_facets = self.configure_faceting() self.fields['possible_facets'].choices = possible_facets self.fields['selected_facets'] = SelectedFacetsField( choices=(), required=False, possible_facets=possible_facets) if self.has_multiple_connections(): wtf = self.get_possible_connections() self.fields['connection'].choices = tuple(wtf) # noqa self.fields['connection'].initial = 'default' else: self.fields['connection'].widget = HiddenInput() def is_haystack1(self): return self.haystack_config.is_version_1x() def is_haystack2(self): return self.haystack_config.is_version_2x() def guess_haystack_version(self): return self.haystack_config.version def has_multiple_connections(self): return self.haystack_config.has_multiple_connections() def get_possible_connections(self): return self.haystack_config.get_connections() def configure_faceting(self): possible_facets = self.haystack_config.get_facets( sqs=self.searchqueryset) return [Facet(x).choices() for x in sorted(possible_facets)] def should_allow_faceting(self): return self.haystack_config.supports_faceting() def __repr__(self): is_valid = self.is_bound and not bool(self._errors) return '<%(module)s.%(cls)s bound=%(is_bound)s valid=%(valid)s ' \ 'version=%(version)d multiple_connections=%(conns)s ' \ 'supports_faceting=%(facets)s>' % { 'module': self.__class__.__module__, 'cls': self.__class__.__name__, 'is_bound': yesno(self.is_bound), 'conns': yesno(self.has_multiple_connections()), 'facets': yesno(self.should_allow_faceting()), 'valid': yesno(is_valid), 'version': self.haystack_config.version, } def no_query_found(self): """ When nothing is entered, show everything, because it's a better useful default for our usage. """ return self.searchqueryset.all() def search(self): sqs = self.searchqueryset.all() if not self.is_valid(): # When nothing is entered, show everything, because it's a better # useful default for our usage. return sqs cleaned_data = getattr(self, 'cleaned_data', {}) connection = cleaned_data.get('connection', ()) if self.has_multiple_connections() and len(connection) == 1: sqs = sqs.using(*connection) if self.should_allow_faceting(): for applied_facet in self.applied_facets(): narrow_query = applied_facet.narrow.format( cleaned_value=sqs.query.clean(applied_facet.value)) sqs = sqs.narrow(narrow_query) to_facet_on = sorted(cleaned_data.get('possible_facets', ())) if len(to_facet_on) > 0: for field in to_facet_on: sqs = sqs.facet(field) only_models = self.get_models() if len(only_models) > 0: sqs = sqs.models(*only_models) content_field = cleaned_data.get('content_field', ['content']) query = cleaned_data.get('q', None) if query and query[0]: if cleaned_data.get("search_type", 0) == "1": kwargs = {content_field[0]: Exact(*query)} sqs = sqs.filter(**kwargs) else: sqs = sqs.auto_query(*query, fieldname=content_field[0]) if self.load_all: sqs = sqs.load_all() return sqs def clean_connection(self): return [self.cleaned_data.get('connection', 'default').strip()] def clean_possible_facets(self): return list(frozenset(self.cleaned_data.get('possible_facets', ()))) def clean_selected_facets(self): return list(frozenset(self.cleaned_data.get('selected_facets', ()))) def clean_q(self): return [self.cleaned_data.get('q', '')] def clean_content_field(self): return [self.cleaned_data.get('content_field', '')] def clean_p(self): page = self.cleaned_data.get('p', None) if page is None: page = self.fields['p'].min_value return [page] def full_clean(self): """ Taken from Django master as of 5e06fa1469180909c51c07151692412269e51ea3 but is mostly a copy-paste all the way back to 1.3.1 Basically we want to keep cleaned_data around, not remove it if errors occured. """ self._errors = ErrorDict() if not self.is_bound: # Stop further processing. return self.cleaned_data = {} # If the form is permitted to be empty, and none of the form data has # changed from the initial data, short circuit any validation. if self.empty_permitted and not self.has_changed(): return self._clean_fields() self._clean_form() self._post_clean() def clean(self): cd = self.cleaned_data selected = 'selected_facets' possible = 'possible_facets' if selected in cd and len(cd[selected]) > 0: if possible not in cd or len(cd[possible]) == 0: raise ValidationError( 'Unable to provide facet counts without selecting a field to facet on' ) return cd def applied_facets(self): cleaned_querydict = self.cleaned_data_querydict return AppliedFacets(querydict=cleaned_querydict) @property def cleaned_data_querydict(self): """ Creates an immutable QueryDict instance from the form's cleaned_data """ query = QueryDict('', mutable=True) # make sure cleaned_data is available, if possible ... self.is_valid() cleaned_data = getattr(self, 'cleaned_data', {}) for key, values in cleaned_data.items(): query.setlist(key=key, list_=values) query._mutable = False return query