def get_values_counts(self, qs): # It is easiest to base queries around the intermediate table, in order # to get counts. through = self.field_obj.rel.through rel_model = self.rel_model assert rel_model != self.model, "Can't cope with this yet..." fkey_this = [ f for f in through._meta.fields if f.rel is not None and f.rel.to is self.model ][0] fkey_other = [ f for f in through._meta.fields if f.rel is not None and f.rel.to is rel_model ][0] # We need to limit items by what is in the main QuerySet (which might # already be filtered). m2m_objs = through.objects.filter(**{fkey_this.name + '__in': qs}) # We need to exclude items in other table that we have already filtered # on, because they are not interesting. m2m_objs = m2m_objs.exclude(**{fkey_other.name + '__in': self.chosen}) # Now get counts: field_name = fkey_other.name return value_counts(m2m_objs, field_name)
def get_values_counts(self, qs): """ Returns a SortedDict dictionary of {value: count}. The order is the underlying order produced by sorting ascending on the DB field. """ return value_counts(qs, self.field)
def get_choices_add(self, qs): chosen = list(self.chosen) range_type = None if not self.drilldown and len(chosen) > 0: return [] all_vals = qs.values_list(self.field).distinct() num = all_vals.count() choices = [] if num <= self.max_links: val_counts = value_counts(qs, self.field) for v, count in val_counts.items(): choice = self.choice_type([RangeEnd(v, True)]) choices.append(FilterChoice(self.render_choice_object(choice), count, self.build_params(add=choice), FILTER_ADD)) else: if self.ranges is None: val_range = qs.aggregate(lower=models.Min(self.field), upper=models.Max(self.field)) ranges = auto_ranges(val_range['lower'], val_range['upper'], self.max_links) else: ranges = self.ranges val_counts = numeric_range_counts(qs, self.field, ranges) for i, (vals, count) in enumerate(val_counts.items()): # For the lower bound, we make it inclusive only if it the first # choice. The upper bound is always inclusive. This gives # filters that behave sensibly e.g. with 10-20, 20-30, 30-40, # the first will include 10 and 20, the second will exlude 20. choice = self.choice_type([RangeEnd(vals[0], i == 0), RangeEnd(vals[1], True)]) choices.append(FilterChoice(self.render_choice_object(choice), count, self.build_params(add=choice), FILTER_ADD)) return choices
def get_choices_add(self, qs): chosen = list(self.chosen) if not self.drilldown and len(chosen) > 0: return [] all_vals = qs.values_list(self.field).distinct() num = all_vals.count() choices = [] if num <= self.max_links: val_counts = value_counts(qs, self.field) for v, count in val_counts.items(): choice = self.choice_type([RangeEnd(v, True)]) choices.append( FilterChoice(self.render_choice_object(choice), count, self.build_params(add=choice), FILTER_ADD)) else: if self.ranges is None: val_range = qs.aggregate(lower=models.Min(self.field), upper=models.Max(self.field)) ranges = auto_ranges(val_range['lower'], val_range['upper'], self.max_links) else: ranges = self.ranges val_counts = numeric_range_counts(qs, self.field, ranges) for i, (vals, count) in enumerate(val_counts.items()): # For the lower bound, we make it inclusive only if it the first # choice. The upper bound is always inclusive. This gives # filters that behave sensibly e.g. with 10-20, 20-30, 30-40, # the first will include 10 and 20, the second will exlude 20. choice = self.choice_type( [RangeEnd(vals[0], i == 0), RangeEnd(vals[1], True)]) choices.append( FilterChoice(self.render_choice_object(choice), count, self.build_params(add=choice), FILTER_ADD)) return choices
def get_values_counts(self, qs): # It is easiest to base queries around the intermediate table, in order # to get counts. through = self.field_obj.rel.through rel_model = self.rel_model assert rel_model != self.model, "Can't cope with this yet..." fkey_this = [f for f in through._meta.fields if f.rel is not None and f.rel.to is self.model][0] fkey_other = [f for f in through._meta.fields if f.rel is not None and f.rel.to is rel_model][0] # We need to limit items by what is in the main QuerySet (which might # already be filtered). m2m_objs = through.objects.filter(**{fkey_this.name + '__in': qs}) # We need to exclude items in other table that we have already filtered # on, because they are not interesting. m2m_objs = m2m_objs.exclude(**{fkey_other.name + '__in': self.chosen}) # Now get counts: field_name = fkey_other.name return value_counts(m2m_objs, field_name)