Skip to content

Commit 12e4845

Browse files
Daan van der Kallendaanvdk
authored andcommitted
Add min_value option to stats
1 parent be1df65 commit 12e4845

File tree

2 files changed

+50
-15
lines changed

2 files changed

+50
-15
lines changed

binder/views.py

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
# annotations: a list of annotation names that have to be applied to the queryset for the expr to work (optional),
4343
Stat = namedtuple(
4444
'Stat',
45-
['expr', 'filters', 'group_by', 'annotations'],
46-
defaults=[{}, None, []],
45+
['expr', 'filters', 'group_by', 'annotations', 'min_value'],
46+
defaults=[{}, None, [], None],
4747
)
4848

4949

@@ -3008,20 +3008,42 @@ def _get_stat(self, request, queryset, stat, annotations, include_annotations):
30083008
}
30093009

30103010
group_by = stat.group_by.replace('.', '__')
3011+
3012+
value = {
3013+
# The jsonloads/jsondumps is to make sure we can handle different
3014+
# types as keys, an example is dates.
3015+
jsonloads(jsondumps(key)): value
3016+
for key, value in (
3017+
queryset
3018+
.order_by()
3019+
.exclude(**{group_by: None})
3020+
.values(group_by)
3021+
.annotate(_binder_stat=stat.expr)
3022+
.values_list(group_by, '_binder_stat')
3023+
)
3024+
}
3025+
3026+
other = 0
3027+
if stat.min_value is not None:
3028+
min_value = stat.min_value * sum(value.values())
3029+
new_value = {}
3030+
3031+
others = 0
3032+
for key, sub_value in value.items():
3033+
if sub_value >= min_value:
3034+
new_value[key] = sub_value
3035+
else:
3036+
other += sub_value
3037+
others += 1
3038+
3039+
if others > 1:
3040+
value = new_value
3041+
else:
3042+
other = 0
3043+
30113044
return {
3012-
'value': {
3013-
# The jsonloads/jsondumps is to make sure we can handle different
3014-
# types as keys, an example is dates.
3015-
jsonloads(jsondumps(key)): value
3016-
for key, value in (
3017-
queryset
3018-
.order_by()
3019-
.exclude(**{group_by: None})
3020-
.values(group_by)
3021-
.annotate(_binder_stat=stat.expr)
3022-
.values_list(group_by, '_binder_stat')
3023-
)
3024-
},
3045+
'value': value,
3046+
'other': other,
30253047
'group_by': stat.group_by,
30263048
'filters': stat.filters,
30273049
}

tests/test_stats.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ def test_animals_by_zoo(self):
4848
self.assertEqual(res, {
4949
'by_zoo': {
5050
'value': {'Zoo 1': 1, 'Zoo 2': 2},
51+
'other': 0,
5152
'filters': {},
5253
'group_by': 'zoo.name',
5354
},
@@ -71,6 +72,7 @@ def test_stats_filtered(self):
7172
},
7273
'by_zoo': {
7374
'value': {'Zoo 1': 1},
75+
'other': 0,
7476
'filters': {},
7577
'group_by': 'zoo.name',
7678
},
@@ -83,3 +85,14 @@ def test_stat_not_found(self):
8385
'message': 'unknown stat: does_not_exist',
8486
'debug': ANY(),
8587
})
88+
89+
def test_animals_by_zoo(self):
90+
res = self.get_stats('by_zoo')
91+
self.assertEqual(res, {
92+
'by_zoo': {
93+
'value': {'Zoo 1': 1, 'Zoo 2': 2},
94+
'other': 0,
95+
'filters': {},
96+
'group_by': 'zoo.name',
97+
},
98+
})

0 commit comments

Comments
 (0)