Projet

Général

Profil

0003-dataviz-change-time-interval-aggregation-internals-6.patch

Valentin Deniaud, 18 janvier 2022 17:09

Télécharger (8,83 ko)

Voir les différences:

Subject: [PATCH 3/5] dataviz: change time interval aggregation internals
 (#60547)

 combo/apps/dataviz/forms.py                   | 10 ++---
 .../migrations/0020_auto_20220118_1103.py     | 27 +++++++++++++
 combo/apps/dataviz/models.py                  | 39 +++++++++++++------
 tests/test_dataviz.py                         | 20 +++++-----
 4 files changed, 69 insertions(+), 27 deletions(-)
 create mode 100644 combo/apps/dataviz/migrations/0020_auto_20220118_1103.py
combo/apps/dataviz/forms.py
57 57
class ChartNgForm(forms.ModelForm):
58 58
    blank_choice = ('', '---------')
59 59
    time_intervals = (
60
        ('_week', _('Week')),
61
        ('_month', _('Month')),
62
        ('_year', _('Year')),
63
        ('_weekday', _('Week day')),
60
        ('week', _('Week')),
61
        ('month', _('Month')),
62
        ('year', _('Year')),
63
        ('weekday', _('Week day')),
64 64
    )
65 65

  
66 66
    class Meta:
......
146 146
        if 'day' not in choice_ids:
147 147
            return
148 148
        for choice in self.time_intervals:
149
            if choice[0].strip('_') not in choice_ids:
149
            if choice[0] not in choice_ids:
150 150
                self.fields['time_interval'].choices.append(choice)
151 151

  
152 152
    def clean(self):
combo/apps/dataviz/migrations/0020_auto_20220118_1103.py
1
# Generated by Django 2.2.19 on 2022-01-18 10:03
2

  
3
from django.db import migrations
4

  
5

  
6
def update_time_intervals(apps, schema_editor):
7
    ChartNgCell = apps.get_model('dataviz', 'ChartNgCell')
8

  
9
    for cell in ChartNgCell.objects.all():
10
        save = False
11
        for param in cell.filter_params:
12
            if param == 'time_interval' and cell.filter_params[param].startswith('_'):
13
                cell.filter_params[param] = cell.filter_params[param][1:]
14
                save = True
15
        if save:
16
            cell.save()
17

  
18

  
19
class Migration(migrations.Migration):
20

  
21
    dependencies = [
22
        ('dataviz', '0019_auto_20211006_1525'),
23
    ]
24

  
25
    operations = [
26
        migrations.RunPython(update_time_intervals, migrations.RunPython.noop),
27
    ]
combo/apps/dataviz/models.py
148 148
    def natural_key(self):
149 149
        return (self.slug, self.site_slug, self.service_slug)
150 150

  
151
    def has_native_support_for_interval(self, time_interval):
152
        # pylint: disable=not-an-iterable
153
        return any(
154
            time_interval == x['id']
155
            for filter_ in self.filters
156
            for x in filter_['options']
157
            if filter_['id'] == 'time_interval'
158
        )
159

  
151 160

  
152 161
TIME_FILTERS = (
153 162
    ('previous-year', _('Previous year')),
......
350 359
            data = response['data']
351 360

  
352 361
            interval = self.filter_params.get('time_interval', '')
353
            if data['x_labels'] and (interval == 'day' or interval.startswith('_')):
362
            if (
363
                data['x_labels']
364
                and interval
365
                and (interval == 'day' or not self.statistic.has_native_support_for_interval(interval))
366
            ):
354 367
                self.aggregate_data(data, interval)
355 368

  
356 369
            chart.x_labels = data['x_labels']
......
421 434
                params['end'] = Template('{{ %s|date:"Y-m-d" }}' % self.time_range_end_template).render(
422 435
                    Context(context)
423 436
                )
424
        if 'time_interval' in params and params['time_interval'].startswith('_'):
437
        if 'time_interval' in params and not self.statistic.has_native_support_for_interval(
438
            params['time_interval']
439
        ):
425 440
            params['time_interval'] = 'day'
426 441
        return params
427 442

  
......
625 640
            # "W" and "o" are interpreted by Django's date filter and should be left as is. First W is
626 641
            # backslash escaped to prevent it from being interpreted, translators should refer to Django's
627 642
            # documentation in order to know if the new letter resulting of translation should be escaped or not.
628
            '_week': gettext(r'\WW-o'),
629
            '_month': 'm-Y',
630
            '_year': 'Y',
631
            '_weekday': 'l',
643
            'week': gettext(r'\WW-o'),
644
            'month': 'm-Y',
645
            'year': 'Y',
646
            'weekday': 'l',
632 647
        }
633 648
        if interval == 'day':
634 649
            x_labels = [
635 650
                format_date(min_date + timedelta(days=i), date_formats['day'])
636 651
                for i in range((max_date - min_date).days + 1)
637 652
            ]
638
        elif interval == '_month':
653
        elif interval == 'month':
639 654
            month_difference = max_date.month - min_date.month + (max_date.year - min_date.year) * 12
640 655
            x_labels = [
641
                format_date(min_date + relativedelta(months=i), date_formats['_month'])
656
                format_date(min_date + relativedelta(months=i), date_formats['month'])
642 657
                for i in range(month_difference + 1)
643 658
            ]
644
        elif interval == '_year':
659
        elif interval == 'year':
645 660
            x_labels = [str(year) for year in range(min_date.year, max_date.year + 1)]
646
        elif interval == '_weekday':
661
        elif interval == 'weekday':
647 662
            x_labels = [str(label) for label in WEEKDAYS.values()]
648
        elif interval == '_week':
663
        elif interval == 'week':
649 664
            x_labels = []
650 665
            date, last_date = min_date, max_date
651 666
            if min_date.weekday() > max_date.weekday():
652 667
                last_date += relativedelta(weeks=1)
653 668
            while date <= last_date:
654
                x_labels.append(format_date(date, date_formats['_week']))
669
                x_labels.append(format_date(date, date_formats['week']))
655 670
                date += relativedelta(weeks=1)
656 671

  
657 672
        aggregates = OrderedDict((label, [0] * len(series_data)) for label in x_labels)
tests/test_dataviz.py
1211 1211
        ('day', False, 'Day'),
1212 1212
        ('month', True, 'Month'),
1213 1213
        ('year', False, 'Year'),
1214
        ('_week', False, 'Week'),
1215
        ('_weekday', False, 'Week day'),
1214
        ('week', False, 'Week'),
1215
        ('weekday', False, 'Week day'),
1216 1216
    ]
1217 1217

  
1218 1218
    ou_field = resp.form[field_prefix + 'ou']
......
1667 1667
    assert time_interval_field.value == 'day'
1668 1668
    assert time_interval_field.options == [
1669 1669
        ('day', True, 'Day'),
1670
        ('_week', False, 'Week'),
1671
        ('_month', False, 'Month'),
1672
        ('_year', False, 'Year'),
1673
        ('_weekday', False, 'Week day'),
1670
        ('week', False, 'Week'),
1671
        ('month', False, 'Month'),
1672
        ('year', False, 'Year'),
1673
        ('weekday', False, 'Week day'),
1674 1674
    ]
1675 1675
    resp.form.submit()
1676 1676
    cell.refresh_from_db()
......
1682 1682
    assert chart.raw_series[0][0][:8] == [0, 0, 0, 0, 0, 0, 0, 1]
1683 1683
    assert chart.raw_series[1][0][:8] == [2, 0, 0, 0, 0, 0, 0, 2]
1684 1684

  
1685
    time_interval_field.value = '_month'
1685
    time_interval_field.value = 'month'
1686 1686
    resp.form.submit()
1687 1687
    cell.refresh_from_db()
1688 1688

  
......
1696 1696
        ([4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], {'title': 'Serie 2'}),
1697 1697
    ]
1698 1698

  
1699
    time_interval_field.value = '_year'
1699
    time_interval_field.value = 'year'
1700 1700
    resp.form.submit()
1701 1701
    cell.refresh_from_db()
1702 1702

  
......
1708 1708
        ([5, 0, 0], {'title': 'Serie 2'}),
1709 1709
    ]
1710 1710

  
1711
    time_interval_field.value = '_weekday'
1711
    time_interval_field.value = 'weekday'
1712 1712
    resp.form.submit()
1713 1713
    cell.refresh_from_db()
1714 1714

  
......
1720 1720
        ([1, 4, 0, 0, 0, 0, 0], {'title': 'Serie 2'}),
1721 1721
    ]
1722 1722

  
1723
    time_interval_field.value = '_week'
1723
    time_interval_field.value = 'week'
1724 1724
    resp.form.submit()
1725 1725
    cell.refresh_from_db()
1726 1726

  
1727
-