This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
publik-bi/bijoe/views.py

138 lines
5.2 KiB
Python

import json
import datetime
import decimal
from django.views.generic import TemplateView, FormView
from django.http import Http404
from django.utils import formats
from django.http import HttpResponse
from .utils import get_warehouses
from .engine import Engine
from .forms import CubeForm
from .ods import Workbook
class HomepageView(TemplateView):
template_name = 'bijoe/homepage.html'
def get_context_data(self, **kwargs):
ctx = super(HomepageView, self).get_context_data(**kwargs)
ctx['warehouses'] = sorted((Engine(w) for w in get_warehouses()), key=lambda w: w.label)
return ctx
class WarehouseView(TemplateView):
template_name = 'bijoe/warehouse.html'
def get_context_data(self, **kwargs):
ctx = super(WarehouseView, self).get_context_data(**kwargs)
try:
ctx['warehouse'] = [warehouse for warehouse in get_warehouses() if warehouse.name ==
self.kwargs['warehouse']][0]
except IndexError:
raise Http404
return ctx
class CubeMixin(object):
def get_data(self, cleaned_data, stringify=True):
cleaned_data = cleaned_data
filters = []
for kw, values in cleaned_data.iteritems():
if values and kw.startswith('filter__'):
dimension_name = kw[8:]
filters.append((dimension_name, values))
measures = cleaned_data.get('measures', [])
drilldown = cleaned_data.get('drilldown', [])
data = []
for row in self.cube.query(filters, drilldown, measures):
data_row = []
for cell, value in row:
if stringify:
if cell.type is float:
value = formats.number_format(value, use_l10n=True) + u' %'
if isinstance(value, datetime.timedelta):
s = ''
if value.days:
s += '%d jour(s)' % value.days
if value.seconds / 3600:
s += ' %d heure(s)' % (value.seconds / 3600)
if not s:
s = 'moins d\'1 heure'
value = s
data_row.append(value)
data.append(data_row)
return data
class CubeView(CubeMixin, FormView):
template_name = 'bijoe/cube.html'
form_class = CubeForm
def dispatch(self, request, *args, **kwargs):
try:
self.warehouse = Engine([warehouse for warehouse in get_warehouses() if warehouse.name
== self.kwargs['warehouse']][0])
except IndexError:
raise Http404
try:
self.cube = self.warehouse[self.kwargs['cube']]
except KeyError:
raise Http404
return super(CubeView, self).dispatch(request, *args, **kwargs)
def get_form_kwargs(self):
kwargs = super(CubeView, self).get_form_kwargs()
kwargs['cube'] = self.cube
return kwargs
def form_valid(self, form):
if 'ods' in self.request.POST:
return self.ods(form)
else:
return self.form_invalid(form)
def ods(self, form):
workbook = Workbook()
sheet = workbook.add_sheet(self.cube.label)
ctx = self.get_context_data(form=form)
for j, m in enumerate(ctx['drilldown'] + ctx['measures']):
sheet.write(0, j, m.label)
for i, row in enumerate(ctx['data']):
for j, cell in enumerate(row):
sheet.write(i + 1, j, unicode(cell))
response = HttpResponse(content_type='application/vnd.oasis.opendocument.spreadsheet')
response['Content-Disposition'] = 'attachment; filename=%s.ods' % self.cube.name
workbook.save(response)
return response
def get_context_data(self, **kwargs):
ctx = super(CubeView, self).get_context_data(**kwargs)
ctx['warehouse'] = self.warehouse
ctx['cube'] = self.cube
form = ctx['form']
if form.is_valid():
ctx['data'] = self.get_data(form.cleaned_data)
ctx['measures'] = [self.cube.measures[measure] for measure in
form.cleaned_data['measures']]
ctx['drilldown'] = [self.cube.dimensions[dimension] for dimension in
form.cleaned_data['drilldown']]
json_data = []
for row in self.get_data(form.cleaned_data, stringify=False):
coords = []
for dimension, cell in zip(ctx['drilldown'], row):
coords.append({'label': dimension.label, 'value': cell})
measures = []
for measure, cell in zip(ctx['measures'], row[len(ctx['drilldown']):]):
if isinstance(cell, datetime.timedelta):
cell = cell.days + cell.seconds / 86400.
if isinstance(cell, decimal.Decimal):
cell = float(cell)
measures.append({'label': measure.label, 'value': cell})
json_data.append({'coords': coords, 'measures': measures})
ctx['json'] = json.dumps(json_data, indent=2)
return ctx