combo/combo/apps/dataviz/utils.py

153 lines
5.0 KiB
Python

# combo - content management system
# Copyright (C) 2015 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import requests
from requests.exceptions import RequestException
import urlparse
from django.utils.translation import ugettext as _
from django.conf import settings
def get_requests_params():
return getattr(settings, 'CUBES_REQUESTS_PARAMS', {})
def get_cubes():
try:
r = requests.get(urlparse.urljoin(settings.CUBES_URL, 'cubes'), **get_requests_params())
except RequestException:
return []
try:
return r.json()
except ValueError:
return []
def get_cube(name):
model_url = urlparse.urljoin(settings.CUBES_URL, 'cube/%s/model' % name)
try:
r = requests.get(model_url, **get_requests_params())
except RequestException:
return None
try:
return r.json()
except ValueError:
return None
def get_drilldown(name):
cube = get_cube(name)
if not cube:
return []
l = []
seen = set()
for dimension in cube.get('dimensions', []):
dim_name = dimension['name']
dim_label = dimension.get('label') or dim_name
if dimension.get('levels'):
levels = {}
for level in dimension['levels']:
levels[level['name']] = level.get('label') or level['name']
if dimension.get('hierarchies'):
for hierarchy in dimension['hierarchies']:
h_name = hierarchy['name']
h_label = hierarchy.get('label') or h_name
if h_name == 'default':
h_label = ''
for i in range(1, len(hierarchy['levels'])+1):
level = hierarchy['levels'][i-1]
label = _(u'by ') + _(u' and ').join(
levels[level] for level in hierarchy['levels'][:i]
)
name = '%s@%s:%s' % (dim_name, h_name, level)
if label not in seen:
l.append((name, label))
seen.add(label)
else:
raise NotImplementedError
else:
l.append((dim_name, _(u'by %s') % dim_label))
return l
def compute_levels(cube, drilldown, key_refs=None, label_refs=None):
from .utils import get_attribute_ref
dim = drilldown.split('@')[0]
hier = drilldown.split('@')[1].split(':')[0]
lev = drilldown.split(':')[1]
for dimension in cube['dimensions']:
if dimension['name'] != dim:
continue
level_label_refs = {}
level_key_refs = {}
for level in dimension['levels']:
level_key_refs[level['name']] = get_attribute_ref(level, level['key'])
level_label_refs[level['name']] = get_attribute_ref(level, level['label_attribute'])
for hierarchy in dimension['hierarchies']:
if hierarchy['name'] != hier:
continue
for level in hierarchy['levels']:
if key_refs is not None:
key_refs.append(level_key_refs[level])
if label_refs is not None:
label_refs.append(level_label_refs[level])
if level == lev:
break
break
break
def get_aggregate(name, aggregate1, drilldown1, drilldown2, other_parameters=None):
if not name:
return None
cube = get_cube(name)
aggregate_url = urlparse.urljoin(settings.CUBES_URL, 'cube/%s/aggregate' % name)
if not aggregate1:
return None
try:
params = {'aggregate': aggregate1}
drilldowns = []
key_refs = []
if drilldown1:
compute_levels(cube, drilldown1, key_refs=key_refs)
drilldowns.append(drilldown1)
if drilldown2:
compute_levels(cube, drilldown2, key_refs=key_refs)
drilldowns.append(drilldown2)
if drilldowns:
params['drilldown'] = drilldowns
if key_refs:
params['order'] = key_refs
if other_parameters:
params.update(other_parameters)
r = requests.get(aggregate_url, params=params, **get_requests_params())
except RequestException:
return None
try:
return r.json()
except ValueError:
return None
def get_attribute_ref(level, name):
for attribute in level['attributes']:
if attribute['name'] == name:
return attribute['ref']