Projet

Général

Profil

0001-add-support-for-boolean-values-fixes-16346.patch

Benjamin Dauvergne, 15 janvier 2019 12:54

Télécharger (10,3 ko)

Voir les différences:

Subject: [PATCH] add support for boolean values (fixes #16346)

 README.rst                            |  3 +--
 bijoe/schemas.py                      |  2 ++
 bijoe/templates/bijoe/cube_table.html |  5 ++--
 bijoe/visualization/forms.py          |  5 +++-
 bijoe/visualization/utils.py          | 27 +++++++++++--------
 tests/fixtures/schema1/01_schema.json |  6 +++++
 tests/fixtures/schema1/01_schema.sql  | 37 ++++++++++++++-------------
 tests/test_schema1.py                 | 15 +++++++++++
 tests/utils.py                        |  2 +-
 9 files changed, 67 insertions(+), 35 deletions(-)
README.rst
81 81
    * join: list of join names, indicate that some joins must be used when using
82 82
      this dimension,
83 83

  
84
    * type: indicate the type of the dimension, numerical, time-like,
85
      geographical, duration, etc..
84
    * type: indicate the type of the dimension: integer, string, bool, date
86 85

  
87 86
    * value: SQL expression giving the value for the dimension,
88 87
      it can be different than the value used for filtering or grouping,
bijoe/schemas.py
250 250
                pass
251 251
            return ' AND '.join(filters), values
252 252
        else:
253
            if not isinstance(filter_values, list):
254
                filter_values = [filter_values]
253 255
            if not filter_values:
254 256
                return '', []
255 257
            if self.type == 'integer':
bijoe/templates/bijoe/cube_table.html
12 12
      {% for row in table.table %}
13 13
        <tr>
14 14
          {% for value in row %}
15
          <td>
16
            {% if value == None %}0{% else %}{{ value }}{% endif %}
17
          </td>
15
          {% comment %}Only django 1.10 allow is None/True/False{% endcomment %}
16
          <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>
18 17
          {% endfor %}
19 18
        </tr>
20 19
      {% endfor %}
bijoe/visualization/forms.py
19 19
from django.core.exceptions import ValidationError
20 20
from django.utils.translation import ugettext as _
21 21
from django.utils.safestring import mark_safe
22
from django.forms import ModelForm, TextInput
22
from django.forms import ModelForm, TextInput, NullBooleanField
23 23
from django.conf import settings
24 24

  
25 25
try:
......
179 179
            if dimension.type == 'date':
180 180
                self.base_fields[field_name] = DateRangeField(
181 181
                    label=dimension.label.capitalize(), required=False)
182
            elif dimension.type == 'bool':
183
                self.base_fields[field_name] = NullBooleanField(
184
                    label=dimension.label.capitalize(), required=False)
182 185
            else:
183 186
                self.base_fields[field_name] = forms.MultipleChoiceField(
184 187
                    label=dimension.label.capitalize(),
bijoe/visualization/utils.py
14 14
# You should have received a copy of the GNU Affero General Public License
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17
import six
17 18
import re
18 19
import json
19 20
import hashlib
......
120 121

  
121 122
    @property
122 123
    def key(self):
123
        l = [self.cube.engine.warehouse.name, self.cube.name]
124
        keys = [self.cube.engine.warehouse.name, self.cube.name]
124 125
        if self.loop:
125
            l.append(self.loop.name)
126
        for kw, values in self.filters.iteritems():
127
            if values:
128
                if isinstance(values, dict):
129
                    values = values.items()
130
                l.append('$'.join([kw] + sorted(map(unicode, values))))
131
        l += [dim.name for dim in self.drilldown]
132
        l += [self.measure.name]
133
        key = '$'.join(v.encode('utf8') for v in l)
126
            keys.append(self.loop.name)
127
        for kw, value in self.filters.iteritems():
128
            if value is None:
129
                continue
130
            elif isinstance(value, (dict, list, tuple)):
131
                # multiple values
132
                if isinstance(value, dict):
133
                    value = value.items()
134
                keys.append('$'.join([kw] + sorted(map(six.text_type, value))))
135
            else:
136
                # scalar values
137
                keys.append(u'%s$%s' % (kw, six.text_type(value)))
138
        keys += [dim.name for dim in self.drilldown]
139
        keys += [self.measure.name]
140
        key = '$'.join(v.encode('utf8') for v in keys)
134 141
        return hashlib.md5(key).hexdigest()
135 142

  
136 143
    def stringified(self):
tests/fixtures/schema1/01_schema.json
74 74
                    "type": "date",
75 75
                    "value": "date"
76 76
                },
77
                {
78
                    "name": "boolean",
79
                    "label": "Boolean",
80
                    "type": "bool",
81
                    "value": "boolean"
82
                },
77 83
                {
78 84
                    "name": "hour",
79 85
                    "type": "integer",
tests/fixtures/schema1/01_schema.sql
20 20
    date date,
21 21
    datetime timestamp with time zone,
22 22
    integer integer,
23
    boolean boolean,
23 24
    cnt integer default(1),
24 25
    innersubcategory_id integer references schema1.subcategory(id),
25 26
    leftsubcategory_id integer references schema1.subcategory(id),
......
44 45
   (3, 0, 'subé9');
45 46

  
46 47

  
47
INSERT INTO facts (date, datetime, integer, cnt, innersubcategory_id, leftsubcategory_id, rightsubcategory_id, outersubcategory_id) VALUES
48
   ('2017-01-01', '2017-01-01 10:00', 1, 10, 1, 1, 1, 1),
49
   ('2017-01-02', '2017-01-02 10:00', 1, 10, 3, 3, 3, 3),
50
   ('2017-01-03', '2017-01-03 10:00', 1, 10, NULL, NULL, NULL, NULL),
51
   ('2017-01-04', '2017-01-04 10:00', 1, 10, 1, 1, 1, 1),
52
   ('2017-01-05', '2017-01-05 10:00', 1, 10, 1, 1, 1, 1),
53
   ('2017-01-06', '2017-01-06 10:00', 1, 10, 1, 1, 1, 1),
54
   ('2017-01-07', '2017-01-07 10:00', 1, 10, 1, 1, 1, 1),
55
   ('2017-01-08', '2017-01-08 10:00', 1, 10, 1, 1, 1, 1),
56
   ('2017-01-09', '2017-01-09 10:00', 1, 10, 1, 1, 1, 1),
57
   ('2017-01-10', '2017-01-10 10:00', 1, 10, 1, 1, 1, 1),
58
   ('2017-02-01', '2017-02-01 10:00', 1, 10, 1, 1, 1, 1),
59
   ('2017-03-01', '2017-03-01 10:00', 1, 10, 1, 1, 1, 1),
60
   ('2017-04-01', '2017-04-01 10:00', 1, 10, 1, 1, 1, 1),
61
   ('2017-05-01', '2017-05-01 10:00', 1, 10, 1, 1, 1, 1),
62
   ('2017-06-01', '2017-06-01 10:00', 1, 10, 1, 1, 1, 1),
63
   ('2017-07-01', '2017-07-01 10:00', 1, 10, 1, 1, 1, 1),
64
   ('2017-08-01', '2017-08-01 10:00', 1, 10, 1, 1, 1, 1);
48
INSERT INTO facts (date, datetime, integer, boolean, cnt, innersubcategory_id, leftsubcategory_id, rightsubcategory_id, outersubcategory_id) VALUES
49
   ('2017-01-01', '2017-01-01 10:00', 1, FALSE, 10, 1, 1, 1, 1),
50
   ('2017-01-02', '2017-01-02 10:00', 1, TRUE, 10, 3, 3, 3, 3),
51
   ('2017-01-03', '2017-01-03 10:00', 1, FALSE, 10, NULL, NULL, NULL, NULL),
52
   ('2017-01-04', '2017-01-04 10:00', 1, FALSE, 10, 1, 1, 1, 1),
53
   ('2017-01-05', '2017-01-05 10:00', 1, TRUE, 10, 1, 1, 1, 1),
54
   ('2017-01-06', '2017-01-06 10:00', 1, FALSE, 10, 1, 1, 1, 1),
55
   ('2017-01-07', '2017-01-07 10:00', 1, TRUE, 10, 1, 1, 1, 1),
56
   ('2017-01-08', '2017-01-08 10:00', 1, FALSE, 10, 1, 1, 1, 1),
57
   ('2017-01-09', '2017-01-09 10:00', 1, TRUE, 10, 1, 1, 1, 1),
58
   ('2017-01-10', '2017-01-10 10:00', 1, FALSE, 10, 1, 1, 1, 1),
59
   ('2017-02-01', '2017-02-01 10:00', 1, TRUE, 10, 1, 1, 1, 1),
60
   ('2017-03-01', '2017-03-01 10:00', 1, FALSE, 10, 1, 1, 1, 1),
61
   ('2017-04-01', '2017-04-01 10:00', 1, TRUE, 10, 1, 1, 1, 1),
62
   ('2017-05-01', '2017-05-01 10:00', 1, FALSE, 10, 1, 1, 1, 1),
63
   ('2017-06-01', '2017-06-01 10:00', 1, TRUE, 10, 1, 1, 1, 1),
64
   ('2017-07-01', '2017-07-01 10:00', 1, FALSE, 10, 1, 1, 1, 1),
65
   ('2017-08-01', '2017-08-01 10:00', 1, TRUE, 10, 1, 1, 1, 1);
tests/test_schema1.py
53 53
        ['2017', '10', '1', '1', '1', '1', '1', '1', '1', '17'],
54 54
        ['Total', '10', '1', '1', '1', '1', '1', '1', '1', '17'],
55 55
    ]
56

  
57

  
58
def test_boolean_dimension(schema1, app, admin):
59
    login(app, admin)
60
    response = app.get('/').follow()
61
    response = response.click('Facts 1')
62
    form = response.form
63
    form.set('representation', 'table')
64
    form.set('measure', 'simple_count')
65
    form.set('drilldown_x', 'boolean')
66
    response = form.submit('visualize')
67
    assert get_table(response) == [['Boolean', 'Non', 'Oui'], ['number of rows', '9', '8']]
68
    form.set('filter__boolean', [o[0] for o in form.fields['filter__boolean'][0].options if o[2] == 'Oui'][0])
69
    response = form.submit('visualize')
70
    assert get_table(response) == [['Boolean', 'Oui'], ['number of rows', '8']]
tests/utils.py
26 26
        row = []
27 27
        table.append(row)
28 28
        for td in tr.findall('td'):
29
            row.append(td.text.strip())
29
            row.append((td.text or '').strip())
30 30
    return table
31 31

  
32
-