diff --git a/avocado/models.py b/avocado/models.py index 48583b1..e5fb986 100644 --- a/avocado/models.py +++ b/avocado/models.py @@ -4,6 +4,7 @@ from warnings import warn from datetime import datetime from django.db import models +from django.db.models import Count from django.contrib.sites.models import Site from django.contrib.auth.models import User, Group from django.utils.encoding import smart_unicode @@ -576,7 +577,7 @@ def coded_values(self, queryset=None): # Data Aggregation Properties def groupby(self, *args, **kwargs): return Aggregator( - self.field, queryset=kwargs.get('queryset', None)).groupby(*args) + self.field, queryset=kwargs.get('queryset')).groupby(*args) @cached_method(version='data_version') def count(self, *args, **kwargs): @@ -589,27 +590,27 @@ def count(self, *args, **kwargs): def max(self, *args, **kwargs): "Returns the maximum value." return Aggregator( - self.field, queryset=kwargs.get('queryset', None)).max(*args) + self.field, queryset=kwargs.get('queryset')).max(*args) @cached_method(version='data_version') def min(self, *args, **kwargs): "Returns the minimum value." return Aggregator( - self.field, queryset=kwargs.get('queryset', None)).min(*args) + self.field, queryset=kwargs.get('queryset')).min(*args) @cached_method(version='data_version') def avg(self, *args, **kwargs): "Returns the average value. Only applies to quantitative data." if self.simple_type == 'number': return Aggregator( - self.field, queryset=kwargs.get('queryset', None)).avg(*args) + self.field, queryset=kwargs.get('queryset')).avg(*args) @cached_method(version='data_version') def sum(self, *args, **kwargs): "Returns the sum of values. Only applies to quantitative data." if self.simple_type == 'number': return Aggregator( - self.field, queryset=kwargs.get('queryset', None)).sum(*args) + self.field, queryset=kwargs.get('queryset')).sum(*args) @cached_method(version='data_version') def stddev(self, *args, **kwargs): @@ -617,7 +618,7 @@ def stddev(self, *args, **kwargs): if self.simple_type == 'number': return Aggregator( self.field, - queryset=kwargs.get('queryset', None)).stddev(*args) + queryset=kwargs.get('queryset')).stddev(*args) @cached_method(version='data_version') def variance(self, *args, **kwargs): @@ -625,7 +626,7 @@ def variance(self, *args, **kwargs): if self.simple_type == 'number': return Aggregator( self.field, - queryset=kwargs.get('queryset', None)).variance(*args) + queryset=kwargs.get('queryset')).variance(*args) @cached_method(version='data_version') def sparsity(self, *args, **kwargs): @@ -646,6 +647,17 @@ def sparsity(self, *args, **kwargs): return nulls / float(count) + @cached_method(version='data_version') + def dist(self, queryset=None): + if queryset is None: + queryset = self.model.objects.all() + + queryset = queryset.annotate(cnt=Count(self.value_field_name))\ + .values_list(self.value_field_name, 'cnt')\ + .order_by(self.value_field_name) + + return tuple(queryset) + # Translator Convenience Methods @property def operators(self): diff --git a/tests/cases/models/tests.py b/tests/cases/models/tests.py index f0fc947..d1d33a0 100644 --- a/tests/cases/models/tests.py +++ b/tests/cases/models/tests.py @@ -325,6 +325,22 @@ def test_random(self): self.assertRaises(ValueError, self.budget.random, 2, queryset=queryset) self.assertEqual(len(self.budget.random(1)), 1) + def test_dist(self): + self.assertEqual(self.first_name.dist(), ( + ('Aaron', 1), + ('Eric', 1), + ('Erick', 1), + ('Erin', 1), + ('Mel', 1), + ('Zac', 1))) + + queryset = self.first_name.model.objects\ + .filter(first_name__startswith='E') + self.assertEqual(self.first_name.dist(queryset=queryset), ( + ('Eric', 1), + ('Erick', 1), + ('Erin', 1))) + class DataConceptTestCase(TestCase): def setUp(self):