add support for string columns (fixes #29768)

This commit is contained in:
Benjamin Dauvergne 2019-01-15 13:57:03 +01:00
parent 973f793f0a
commit 6974f1f56e
7 changed files with 85 additions and 26 deletions

View File

@ -254,14 +254,20 @@ class Dimension(Base):
filter_values = [filter_values]
if not filter_values:
return '', []
is_none = None in filter_values
filter_values = [v for v in filter_values if v is not None]
if self.type == 'integer':
values = map(int, filter_values)
values = [int(v) for v in filter_values]
else:
values = filter_values
s = ', '.join(['%s'] * len(values))
if self.filter_expression:
return self.filter_expression % s, values
return '%s IN (%s)' % (value, s), values
expression = self.filter_expression % s
else:
expression = '%s IN (%s)' % (value, s)
if is_none:
expression = '((%s) OR (%s IS NULL))' % (expression, value)
return expression, values
def join_kind(kind):

View File

@ -13,7 +13,7 @@
<tr>
{% for value in row %}
{% comment %}Only django 1.10 allow is None/True/False{% endcomment %}
<td>{% if value|stringformat:"r" == "None" %}0{% elif value|stringformat:"r" == "True" %}{% trans "Oui" %}{% elif value|stringformat:"r" == "False" %}{% trans "Non" %}{% else %}{{ value }}{% endif %}</td>
<td>{{ value }}</td>
{% endfor %}
</tr>
{% endfor %}

View File

@ -15,10 +15,12 @@
# 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/>.
from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _
from django.utils.safestring import mark_safe
from django.utils import six
from django.forms import ModelForm, TextInput, NullBooleanField
from django.conf import settings
@ -183,9 +185,23 @@ class CubeForm(forms.Form):
self.base_fields[field_name] = NullBooleanField(
label=dimension.label.capitalize(), required=False)
else:
self.base_fields[field_name] = forms.MultipleChoiceField(
members = []
for _id, label in dimension.members:
members.append((_id, six.text_type(_id), label))
members.append((None, '__none__', _('None')))
def coercion_function(members):
def f(v):
for value, s, label in members:
if v == s:
return value
return None
return f
self.base_fields[field_name] = forms.TypedMultipleChoiceField(
label=dimension.label.capitalize(),
choices=dimension.members,
choices=[(s, label) for v, s, label in members],
coerce=coercion_function(members),
required=False,
widget=build_select2_multiple_widget())

View File

@ -159,6 +159,12 @@ class Visualization(object):
if not s:
s = 'moins d\'1 heure'
value = s
elif value is not None and cell['type'] == 'bool':
value = _('Yes') if value else _('No')
elif value is None and cell['type'] in ('duration','integer'):
value = 0
elif value is None and cell['type'] != 'integer':
value = _('None')
cell['value'] = value
return data
@ -179,12 +185,21 @@ class Visualization(object):
def table(self):
table = []
if len(self.drilldown) == 2:
if self.measure.type == 'integer':
default = 0
elif self.measure.type == 'duration':
default = '0 s'
elif self.measure.type == 'percent':
default = '0 %'
else:
raise NotImplementedError(self.measure.type)
x_labels = [x.label for x in self.drilldown_x.members]
y_labels = [y.label for y in self.drilldown_y.members]
used_x_label = set()
used_y_label = set()
grid = {(x, y): None for x in x_labels for y in y_labels}
grid = {(x, y): default for x in x_labels for y in y_labels}
for row in self.stringified():
x_label = unicode(row[0]['value'])

View File

@ -157,6 +157,12 @@
"value": "outercategory.id",
"order_by": "outercategory.ord",
"value_label": "outercategory.label"
},
{
"name": "string",
"label": "String",
"type": "string",
"value": "string"
}
],
"measures": [

View File

@ -25,7 +25,8 @@ CREATE TABLE facts (
innersubcategory_id integer references schema1.subcategory(id),
leftsubcategory_id integer references schema1.subcategory(id),
rightsubcategory_id integer references schema1.subcategory(id),
outersubcategory_id integer references schema1.subcategory(id)
outersubcategory_id integer references schema1.subcategory(id),
string varchar
);
INSERT INTO category (ord, label) VALUES
@ -45,21 +46,21 @@ INSERT INTO subcategory (category_id, ord, label) VALUES
(3, 0, 'subé9');
INSERT INTO facts (date, datetime, integer, boolean, cnt, innersubcategory_id, leftsubcategory_id, rightsubcategory_id, outersubcategory_id) VALUES
('2017-01-01', '2017-01-01 10:00', 1, FALSE, 10, 1, 1, 1, 1),
('2017-01-02', '2017-01-02 10:00', 1, TRUE, 10, 3, 3, 3, 3),
('2017-01-03', '2017-01-03 10:00', 1, FALSE, 10, NULL, NULL, NULL, NULL),
('2017-01-04', '2017-01-04 10:00', 1, FALSE, 10, 1, 1, 1, 1),
('2017-01-05', '2017-01-05 10:00', 1, TRUE, 10, 1, 1, 1, 1),
('2017-01-06', '2017-01-06 10:00', 1, FALSE, 10, 1, 1, 1, 1),
('2017-01-07', '2017-01-07 10:00', 1, TRUE, 10, 1, 1, 1, 1),
('2017-01-08', '2017-01-08 10:00', 1, FALSE, 10, 1, 1, 1, 1),
('2017-01-09', '2017-01-09 10:00', 1, TRUE, 10, 1, 1, 1, 1),
('2017-01-10', '2017-01-10 10:00', 1, FALSE, 10, 1, 1, 1, 1),
('2017-02-01', '2017-02-01 10:00', 1, TRUE, 10, 1, 1, 1, 1),
('2017-03-01', '2017-03-01 10:00', 1, FALSE, 10, 1, 1, 1, 1),
('2017-04-01', '2017-04-01 10:00', 1, TRUE, 10, 1, 1, 1, 1),
('2017-05-01', '2017-05-01 10:00', 1, FALSE, 10, 1, 1, 1, 1),
('2017-06-01', '2017-06-01 10:00', 1, TRUE, 10, 1, 1, 1, 1),
('2017-07-01', '2017-07-01 10:00', 1, FALSE, 10, 1, 1, 1, 1),
('2017-08-01', '2017-08-01 10:00', 1, TRUE, 10, 1, 1, 1, 1);
INSERT INTO facts (date, datetime, integer, boolean, cnt, innersubcategory_id, leftsubcategory_id, rightsubcategory_id, outersubcategory_id, string) VALUES
('2017-01-01', '2017-01-01 10:00', 1, FALSE, 10, 1, 1, 1, 1, 'a'),
('2017-01-02', '2017-01-02 10:00', 1, TRUE, 10, 3, 3, 3, 3, 'b'),
('2017-01-03', '2017-01-03 10:00', 1, FALSE, 10, NULL, NULL, NULL, NULL, 'a'),
('2017-01-04', '2017-01-04 10:00', 1, FALSE, 10, 1, 1, 1, 1, 'a'),
('2017-01-05', '2017-01-05 10:00', 1, TRUE, 10, 1, 1, 1, 1, 'c'),
('2017-01-06', '2017-01-06 10:00', 1, FALSE, 10, 1, 1, 1, 1, NULL),
('2017-01-07', '2017-01-07 10:00', 1, TRUE, 10, 1, 1, 1, 1, 'a'),
('2017-01-08', '2017-01-08 10:00', 1, FALSE, 10, 1, 1, 1, 1, 'a'),
('2017-01-09', '2017-01-09 10:00', 1, TRUE, 10, 1, 1, 1, 1, 'a'),
('2017-01-10', '2017-01-10 10:00', 1, FALSE, 10, 1, 1, 1, 1, 'a'),
('2017-02-01', '2017-02-01 10:00', 1, TRUE, 10, 1, 1, 1, 1, 'a'),
('2017-03-01', '2017-03-01 10:00', 1, FALSE, 10, 1, 1, 1, 1, 'c'),
('2017-04-01', '2017-04-01 10:00', 1, TRUE, 10, 1, 1, 1, 1, 'a'),
('2017-05-01', '2017-05-01 10:00', 1, FALSE, 10, 1, 1, 1, 1, 'a'),
('2017-06-01', '2017-06-01 10:00', 1, TRUE, 10, 1, 1, 1, 1, 'c'),
('2017-07-01', '2017-07-01 10:00', 1, FALSE, 10, 1, 1, 1, 1, 'a'),
('2017-08-01', '2017-08-01 10:00', 1, TRUE, 10, 1, 1, 1, 1, 'b');

View File

@ -68,3 +68,18 @@ def test_boolean_dimension(schema1, app, admin):
form.set('filter__boolean', [o[0] for o in form.fields['filter__boolean'][0].options if o[2] == 'Oui'][0])
response = form.submit('visualize')
assert get_table(response) == [['Boolean', 'Oui'], ['number of rows', '8']]
def test_string_dimension(schema1, app, admin):
login(app, admin)
response = app.get('/').follow()
response = response.click('Facts 1')
form = response.form
form.set('representation', 'table')
form.set('measure', 'simple_count')
form.set('drilldown_x', 'string')
response = form.submit('visualize')
assert get_table(response) == [['String', 'a', 'b', 'c', 'Aucun(e)'], ['number of rows', '11', '2', '3', '1']]
form.set('filter__string', ['a', 'b', '__none__'])
response = form.submit('visualize')
assert get_table(response) == [['String', 'a', 'b', 'Aucun(e)'], ['number of rows', '11', '2', '1']]