def build_query(self, **filters): """ Creates a dict of dictionaries suitable for passing to the SearchQuerySet `facet`, `date_facet` or `query_facet` method. All key word arguments should be wrapped in a list. :param view: API View :param dict[str, list[str]] filters: is an expanded QueryDict or a mapping of keys to a list of parameters. """ field_facets = {} date_facets = {} query_facets = {} facet_serializer_cls = self.view.get_facet_serializer_class() if self.view.lookup_sep == ":": raise AttributeError("The %(cls)s.lookup_sep attribute conflicts with the HaystackFacetFilter " "query parameter parser. Please choose another `lookup_sep` attribute " "for %(cls)s." % {"cls": self.view.__class__.__name__}) fields = facet_serializer_cls.Meta.fields exclude = facet_serializer_cls.Meta.exclude field_options = facet_serializer_cls.Meta.field_options for field, options in filters.items(): if field not in fields or field in exclude: continue field_options = merge_dict(field_options, {field: self.parse_field_options(self.view.lookup_sep, *options)}) valid_gap = ("year", "month", "day", "hour", "minute", "second") for field, options in field_options.items(): if any([k in options for k in ("start_date", "end_date", "gap_by", "gap_amount")]): if not all(("start_date", "end_date", "gap_by" in options)): raise ValueError("Date faceting requires at least 'start_date', 'end_date' " "and 'gap_by' to be set.") if not options["gap_by"] in valid_gap: raise ValueError("The 'gap_by' parameter must be one of %s." % ", ".join(valid_gap)) options.setdefault("gap_amount", 1) date_facets[field] = field_options[field] else: field_facets[field] = field_options[field] return { "date_facets": date_facets, "field_facets": field_facets, "query_facets": query_facets }
def test_utils_merge_dict(self): self.assertEqual(merge_dict(self.dict_a, self.dict_b), { "person": { "gender": "male", "firstname": "Sherlock", "lastname": "Holmes", "location": { "address": "221B Baker Street" }, "combat_proficiency": [ "Martial arts", "Pistol", "boxing", "sword", ] } })
def test_utils_merge_dict(self): self.assertEqual( merge_dict(self.dict_a, self.dict_b), { "person": { "gender": "male", "firstname": "Sherlock", "lastname": "Holmes", "location": {"address": "221B Baker Street"}, "combat_proficiency": [ "Martial arts", "Pistol", "boxing", "sword", ], } }, )
def build_query(self, **filters): """ Creates a dict of dictionaries suitable for passing to the SearchQuerySet `facet`, `date_facet` or `query_facet` method. All key word arguments should be wrapped in a list. :param view: API View :param dict[str, list[str]] filters: is an expanded QueryDict or a mapping of keys to a list of parameters. """ field_facets = {} date_facets = {} query_facets = {} range_facets = {} heatmap_facets = {} facets_options = {} facet_serializer_cls = self.view.get_facet_serializer_class() if self.view.lookup_sep == ":": raise AttributeError( "The %(cls)s.lookup_sep attribute conflicts with the " "HaystackFacetFilter query parameter parser. Please choose " "another `lookup_sep` attribute for %(cls)s." % {"cls": self.view.__class__.__name__}) fields = facet_serializer_cls.Meta.fields exclude = facet_serializer_cls.Meta.exclude field_options = facet_serializer_cls.Meta.field_options for field, options in filters.items(): if not field.startswith("facet.field."): continue field = field[len("facet.field."):] if field not in fields or field in exclude: continue field_options = merge_dict( field_options, {field: self.parse_field_options(*options)}) for field, options in filters.items(): if not field.startswith("facet.heatmap."): continue field = field[len("facet.heatmap."):] if field not in fields or field in exclude: continue heatmap_options = self.parse_field_options(*options) heatmap_facets[field] = heatmap_options valid_gap = ("year", "month", "day", "hour", "minute", "second") for field, options in field_options.items(): if any([ k in options for k in ("start_date", "end_date", "gap_by", "gap_amount") ]): if not all(("start_date", "end_date", "gap_by" in options)): raise ValueError( "Date faceting requires at least 'start_date', " "'end_date' and 'gap_by' to be set.") if not options["gap_by"] in valid_gap: raise ValueError( "The 'gap_by' parameter must be one of %s." % ", ".join(valid_gap)) options.setdefault("gap_amount", 1) date_facets[field] = field_options[field] elif any([k in options for k in ("start", "end", "gap")]): if not all(("start", "end", "gap" in options)): raise ValueError( "Range faceting requires at least 'start', 'end' " "and 'gap' to be set.") range_facets[field] = field_options[field] else: field_facets[field] = field_options[field] for field, options in filters.items(): if field in ("facet.mincount", "facet.missing"): facets_options[field] = options return { "date_facets": date_facets, "field_facets": field_facets, "query_facets": query_facets, "range_facets": range_facets, "facets_options": facets_options, "heatmap_facets": heatmap_facets, }
def test_utils_merge_dict_invalid_input(self): self.assertEqual(merge_dict(self.dict_a, "I'm not a dict!"), "I'm not a dict!")