API Reference

How to retrieve data

DataPool

DataPool.__init__(series)

Create a DataPool object as specified by the series.

Arguments:
  • series (list of dict) - specifies the what data to retrieve and where to retrieve it from. It is of the form

    [{'options': {
       'source': a django model, Manager or QuerySet,
       },
     'terms': [
       'a_valid_field_name', ... ,
       {'any_name': 'a_valid_field_name', ... },
       ]
    },
    ...
    ]
    

    Where

    • options (required) - a dict. Any of the series options for the Highcharts options object are valid.
    • terms - is a list. Each element in terms is either
      1. a str - needs to be a valid model field for the corresponding source, or
      2. a dict - need to be of the form {'any_name': 'a_valid_field_name', ...}.

    To retrieve data from multiple models or QuerySets, just add more dictionaries with the corresponding options and terms.

Raises:
  • APIInputError - sif the series argument has any invalid parameters.

Warning

All elements in terms must be unique across all the dictionaries in the series list. If there are two terms with same name, the latter one is going to overwrite the one before it.

For example, the following is wrong:

[{'options': {
    'source': SomeModel},
  'terms':[
    'foo',
    'bar']},
 {'options': {
    'source': OtherModel},
  'terms':[
    'foo']}]

In this case, the term foo from OtherModel is going to overwrite foo from SomeModel.

Here is the right way of retrieving data from two different models both of which have the same field name.

[{'options': {
   'source': SomeModel},
  'terms':[
    'foo',
    'bar']},
 {'options': {
   'source': OtherModel},
  'terms':[
    {'foo_2': 'foo'}]}]

PivotDataPool

PivotDataPool.__init__(series, top_n_term=None, top_n=None, pareto_term=None, sortf_mapf_mts=None)

Creates a PivotDataPool object.

Arguments:
  • series (required) - a list of dicts that specifies the what data to retrieve, where to retrieve it from and how to pivot the data. It is of the form

    [{'options': {
        'source': django Model, Manager or QuerySet ,
        'categories': ['a_valid_field', ...],
        'legend_by': ['a_valid_field', ...] (optional),
        'top_n_per_cat': a number (optional),
      },
      'terms': {
        'any_name_here': django Aggregate,
        'some_other_name':{
          'func': django Aggregate,
          #any options to override
          ...
        },
      ...
      }
     },
     ... #repeat dicts with 'options' & 'terms'
    ]
    

    Where

    • options - is a dict that specifies the common options for all the terms.

      • source (required) - is either a Model, Manager or a QuerySet.

      • categories (required) - is a list of model fields by which the data needs to be pivoted by. If there is only a single item, categories can just be a string instead of a list with single element.

        For example if you have a model with country, state, county, city, date, rainfall, temperature and you want to pivot the data by country and state, then categories = ['country', 'state'] .

        Note

        Order of elements in the categories list matters!

        categories = ['country', 'state'] groups your data first by country and then by state when running the SQL query. This obviously is not the same as grouping by state first and then by country.

      • legend_by (optional) - is a list of model fields by which the data needs to be legended by. For example, in the above case, if you want to legend by county and city, then legend_by = ['county', 'city']

        Note

        Order of elements in the legend_by list matters!

        See the note in categories above.

      • top_n_per_cat (optional) - The number of top items that the legended entries need to be limited to in each category. For example, in the above case, if you wanted only the top 3 county/cities with highest rainfall for each of the country/state, then top_n_per_cat = 3.

    • terms - is a dict. The keys can be any strings (but helps if they are meaningful aliases for the field). The values can either be

      • a django Aggregate : of a valid field in corresponding model. For example, Avg('temperature'), Sum('price'), etc. or
      • a dict: In this case the func must specify relevant django aggregate to retrieve. For example 'func': Avg('price'). The dict can also have any additional entries from the options dict. Any entries here will override the entries in the options dict.
  • top_n_term (optional) - a string. Must be one of the keys in the corresponding terms in the series argument.

  • top_n (optional) - an integer. The number of items for the corresponding top_n_term that need to be retained.

    If top_n_term and top_n are present, only the top_n numberof items are going to displayed in the pivot chart. For example, if you want to plot only the top 5 states with highest average rainfall, you can do something like this.

    PivotDataPool(
      series = [
         {'options': {
            'source': RainfallData.objects.all(),
            'categories': 'state'},
          'terms': {
            'avg_rain': Avg('rainfall')}}],
      top_n_term = 'avg_rain',
      top_n = 5)
    

    Note that the top_n_term is 'avg_rain' and not state; because we want to limit by the average rainfall.

  • pareto_term (optional) - the term with respect to which the pivot chart needs to be paretoed by.

    For example, if you want to plot the average rainfall on the y-axis w.r.t the state on the x-axis and want to pareto by the average rainfall, you can do something like this.

    PivotDataPool(
      series = [
         {'options': {
            'source': RainfallData.objects.all(),
            'categories': 'state'},
          'terms': {
            'avg_rain': Avg('rainfall')}}],
      pareto_term = 'avg_rain')
    
  • sortf_mapf_mts (optional) - a tuple with three elements of the form (sortf, mapf, mts) where

    • sortf - is a function (or a callable) that is used as a key when sorting the category values.

      For example, if categories = 'month_num' and if the months need to be sorted in reverse order, then sortf can be

      sortf = lambda *x: (-1*x[0],)
      

      Note

      sortf is passed the category values as tuples and must return tuples!

      If categories is ['city', 'state'] and if the category values returned need to be sorted with state first and then city, then sortf can be

      sortf = lambda *x: (x[1], x[0])
      

      The above sortf is passed tuples like ('San Francisco', 'CA'), ('New York', 'NY'), ... and it returns tuples like ('CA', 'San Francisco'), ('NY', 'New York'), ... which when used as keys to sort the category values will obviously first sort by state and then by city.

    • mapf - is a function (or a callable) that defines how the category values need to be mapped.

      For example, let’s say categories is 'month_num' and that the category values that are retrieved from your database are 1, 2, 3, etc. If you want month names as the category values instead of month numbers, you can define a mapf to transform the month numbers to month names like so

      def month_name(*t):
          names ={1: 'Jan', 2: 'Feb', 3: 'Mar', 4: 'Apr',
                  5: 'May', 6: 'Jun', 7: 'Jul', 8: 'Aug',
                  9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dec'}
          month_num = t[0]
          return (names[month_num], )
      
      mapf = month_name
      

      Note

      mapf like sortf is passed the category values as tuples and must return tuples.

    • mts - map then sort ; a bool. If True, the category values are mapped first and then sorted, and if False category values are sorted first and then mapped.

      In the above example of month names, we mts must be False because the months must first be sorted based on their number and then mapped to their names. If mts is True, the month numbers would be transformed to the month names, and then sorted, which would yield an order like Apr, Aug, Dec, etc. (not what we want).

Raises:
  • APIInputError - if the series argument has any invalid parameters.

Here is a full example of a series term that retrieves the average temperature of the top 3 cities in each country/state and the average rainfall of the top 2 cities in each country/state.

[{'options': {
    'source': Weather.objects.all(),
    'categories': ['country', 'state'],
    'legend_by': 'city',
    'top_n_per_cat': 3},
  'terms': {
    'avg_temp': Avg('temperature'),
    'avg_rain': {
      'func': Avg('rainfall'),
      'top_n_per_cat': 2}}}]

The 'top_n_per_cat': 2 term in avg_rain dict overrides 'top_n_per_cat': 5 from the comon options dict. Effectively, the above series retrieves the top 2 cities with highest avg_rain in each country/state and top 3 cities with highest avg_temp in each country/state.

A single PivotDataPool can hold data from multiple Models. If there are more models or QuerySets to retrieve the data from, just add more dicts to the series list with different source values.

Warning

The keys for the terms must be unique across all the dictionaries in the series list! If there are multiple terms with same key, the latter ones will just overwrite the previous ones.

For instance, the following example is wrong.

[{'options': {
    'source': EuropeWeather.objects.all(),
    'categories': ['country', 'state']},
  'terms': {
    'avg_temp': Avg('temperature')}},
 {'options': {
     'source': AsiaWeather.objects.all(),
     'categories': ['country', 'state']},
  'terms': {
    'avg_temp': Avg('temperature')}}]

The second avg_temp will overwrite the first one. Instead just use different names for each of the keys in all the dictionaries. Here is the right format.

[{'options': {
    'source': EuropeWeather.objects.all(),
    'categories': ['country', 'state']},
  'terms': {
    'europe_avg_temp': Avg('temperature')}},
 {'options': {
     'source': AsiaWeather.objects.all(),
     'categories': ['country', 'state']},
  'terms': {
    'asia_avg_temp': Avg('temperature')}}]

How to create the charts

Chart

Chart.__init__(datasource, series_options, chart_options=None, x_sortf_mapf_mts=None)

Chart accept the datasource and some options to create the chart and creates it.

Arguments:

  • datasource (required) - a DataPool object that holds the terms and other information to plot the chart from.

  • series_options (required) - specifies the options to plot the terms on the chart. It is of the form

    [{'options': {
        #any items from HighChart series. For ex.,
        'type': 'column'
       },
       'terms': {
         'x_name': ['y_name',
                    {'other_y_name': {
                       #overriding options}},
                    ...],
         ...
         },
       },
      ... #repeat dicts with 'options' & 'terms'
      ]
    

    Where -

    • options (required) - a dict. Any of the parameters from the Highcharts options object - series array are valid as entries in the options dict except data (because data array is generated from your datasource by chartit). For example, type, xAxis, etc. are all valid entries here.

      Note

      The items supplied in the options dict are not validated to make sure that Highcharts actually supports them. Any invalid options are just passed to Highcharts JS which silently ignores them.

    • terms (required) - a dict. keys are the x-axis terms and the values are lists of y-axis terms for that particular x-axis term. Both x-axis and y-axis terms must be present in the corresponding datasource, otherwise an APIInputError is raised.

      The entries in the y-axis terms list must either be a str or a dict. If entries are dicts, the keys need to be valid y-term names and the values need to be any options to override the default options. For example,

      [{'options': {
          'type': 'column',
          'yAxis': 0},
        'terms': {
          'city': [
            'temperature',
           {'rainfall': {
              'type': 'line',
              'yAxis': 1}}]}}]
      

      plots a column chart of city vs. temperature as a line chart on yAxis: 0 and city vs. rainfall as a line chart on yAxis: 1. This can alternatively be expressed as two separate entries:

      [{'options': {
          'type': 'column',
          'yAxis': 0},
        'terms': {
          'city': [
            'temperature']}},
       {'options': {
          'type': 'line',
          'yAxis': 1},
        'terms': {
          'city': [
            'rainfall']}}]
      
  • chart_options (optional) - a dict. Any of the options from the Highcharts options object are valid (except the options in the series array which are passed in the series_options argument. The following chart_options for example, set the chart title and the axes titles.

    {'chart': {
       'title': {
         'text': 'Weather Chart'}},
     'xAxis': {
       'title': 'month'},
     'yAxis': {
       'title': 'temperature'}}
    

    Note

    The items supplied in the chart_options dict are not validated to make sure that Highcharts actually supports them. Any invalid options are just passed to Highcharts JS which silently ignores them.

Raises:

  • APIInputError if any of the terms are not present in the corresponding datasource or if the series_options cannot be parsed.

PivotChart

PivotChart.__init__(datasource, series_options, chart_options=None)

Creates the PivotChart object.

Arguments:

  • datasource (required) - a PivotDataPool object that holds the terms and other information to plot the chart from.

  • series_options (required) - specifies the options to plot the terms on the chart. It is of the form

    [{'options': {
        #any items from HighChart series. For ex.
        'type': 'column'
        },
      'terms': [
        'a_valid_term',
        'other_valid_term': {
          #any options to override. For ex.
         'type': 'area',
          ...
          },
        ...
        ]
      },
      ... #repeat dicts with 'options' & 'terms'
      ]
    

    Where -

    • options (required) - a dict. Any of the parameters from the Highcharts options object - series array are valid as entries in the options dict except data (because data array is generated from your datasource by chartit). For example, type, xAxis, etc. are all valid entries here.

      Note

      The items supplied in the options dict are not validated to make sure that Highcharts actually supports them. Any invalid options are just passed to Highcharts JS which silently ignores them.

    • terms (required) - a list. Only terms that are present in the corresponding datasource are valid.

      Note

      All the terms are plotted on the y-axis. The categories of the datasource are plotted on the x-axis. There is no option to override this.

      Each of the terms must either be a str or a dict. If entries are dicts, the keys need to be valid terms and the values need to be any options to override the default options. For example,

      [{'options': {
          'type': 'column',
          'yAxis': 0},
        'terms': [
          'temperature',
          {'rainfall': {
              'type': 'line',
              'yAxis': 1}}]}]
      

      plots a pivot column chart of temperature on yAxis: 0 and a line pivot chart of rainfall on yAxis: 1. This can alternatively be expressed as two separate entries:

      [{'options': {
          'type': 'column',
          'yAxis': 0},
        'terms': [
            'temperature']},
       {'options': {
          'type': 'line',
          'yAxis': 1},
        'terms': [
            'rainfall']}]
      
  • chart_options (optional) - a dict. Any of the options from the Highcharts options object are valid (except the options in the series array which are passed in the series_options argument. The following chart_options for example, set the chart title and the axes titles.

    {'chart': {
       'title': {
         'text': 'Weather Chart'}},
     'xAxis': {
       'title': 'month'},
     'yAxis': {
       'title': 'temperature'}}
    

    Note

    The items supplied in the chart_options dict are not validated to make sure that Highcharts actually supports them. Any invalid options are just passed to Highcharts JS which silently ignores them.

Raises:

  • APIInputError if any of the terms are not present in the corresponding datasource or if the series_options cannot be parsed.

How to use chartit django template filters

chartit.templatetags.chartit.load_charts(chart_list=None, render_to='')

Loads the Chart/PivotChart objects in the chart_list to the HTML elements with id’s specified in render_to.

Arguments:
  • chart_list - a list of Chart/PivotChart objects. If there is just a single element, the Chart/PivotChart object can be passed directly instead of a list with a single element.

  • render_to - a comma separated string of HTML element id’s where the charts needs to be rendered to. If the element id of a specific chart is already defined during the chart creation, the render_to for that specific chart can be an empty string or a space.

    For example, render_to = 'container1, , container3' renders three charts to three locations in the HTML page. The first one will be rendered in the HTML element with id container1, the second one to it’s default location that was specified in chart_options when the Chart/PivotChart object was created, and the third one in the element with id container3.

Returns:
  • a JSON array of the HighCharts Chart options. Also returns a link to the chartloader.js javascript file to be embedded in the webpage. The chartloader.js has a jQuery script that renders a HighChart for each of the options in the JSON array

Quick Reference for series and series_options

PivotDataPool series PivotChart series_options
[{'options': {
    'source': SomeModel.objects.all(),
    'top_n_per_cat': 10, ...
    }
  'terms': {
    'any_name_here': Sum('a_valid_field'),
    'some_other_name':{
      'func': Avg('a_valid_field),
      #any options to override
      ...
      },
    ...
    }
 },
 ... #repeat dicts with 'options' & 'terms'
 ]
[{'options': {
    #any items from HighChart series. For ex.
    'type': 'column'
    },
  'terms': [
    'a_valid_term',
    'other_valid_term': {
      #any options to override. For ex.
      'type': 'area',
      ...
      },
    ...
    ]
  },
  ... #repeat dicts with 'options' & 'terms'
  ]
DataPool series Chart series_options
[{'options': {
    'source': SomeModel.objects.all(),

    }
  'terms': [
    'a_valid_field_name',
    ..., # more valid field names
    {'any_name': 'a_valid_field_name',
     ... # more name:field_name pairs
     },
    ]
 },
 ... #repeat dicts with 'options' & 'terms'
 ]
[{'options': {
    #any items from HighChart series. For ex.
    'type': 'column'
    },
  'terms': {
    'x_name': ['y_name', 'y_name', ...],
    # only corresponding keys from DataPool
    # terms are valid names.
    ...

    }
  },
  ... #repeat dicts with 'options' & 'terms'
  ]