forked from karthikrish/django-utils
/
models.py
182 lines (134 loc) · 5.7 KB
/
models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
import datetime
try:
import cPickle as pickle
except ImportError:
import pickle
from django.db import models
from django.db.models import Max, Avg
from django.template.defaultfilters import slugify
from djutils.dashboard.registry import registry
PANEL_AGGREGATE_MINUTE = 0
PANEL_AGGREGATE_HOUR = 1
PANEL_AGGREGATE_DAY = 2
PANEL_AGGREGATE_CHOICES = (
(PANEL_AGGREGATE_MINUTE, 'minute'),
(PANEL_AGGREGATE_HOUR, 'hour'),
(PANEL_AGGREGATE_DAY, 'day'),
)
class PanelManager(models.Manager):
def update_panels(self):
data = []
shared_now = datetime.datetime.now()
# function to sort the panels by priority
key = lambda obj: obj.get_priority()
for provider in sorted(registry.get_provider_instances(), key=key):
# pull the data off the panel and store
panel_obj = provider.get_panel_instance()
panel_data_obj = PanelData.objects.create(
panel=panel_obj,
created_date=shared_now,
aggregate_type=PANEL_AGGREGATE_MINUTE,
)
raw_panel_data = provider.get_data()
for key, value in raw_panel_data.items():
data_set_obj = PanelDataSet.objects.create(
panel_data=panel_data_obj,
key=key,
value=value,
)
data.append(panel_data_obj)
return data
def _generate_aggregate(self, timedelta, aggregate_type, seed):
data = []
shared_now = seed or datetime.datetime.now()
low_date = shared_now - timedelta
# function to sort the panels by priority
key = lambda obj: obj.get_priority()
for provider in sorted(registry.get_provider_instances(), key=key):
# pull the data off the panel and store
panel_obj = provider.get_panel_instance()
# create a new panel data object to store the aggregates
panel_data_obj = PanelData.objects.create(
panel=panel_obj,
created_date=shared_now,
aggregate_type=aggregate_type,
)
# get the panel data queryset for the previous `timedelta`
data_qs = panel_obj.data.minute_data().filter(created_date__range=(
low_date, shared_now
))
# get what we really want, which are the k/v pairs
data_sets = PanelDataSet.objects.filter(panel_data__in=data_qs)
# find the unique keys and aggregate over them
distinct_keys = data_sets.values_list('key', flat=True).distinct()
for key in distinct_keys:
# calculate the average and store it
average = data_sets.filter(key=key).aggregate(
average=Avg('value')
)['average']
PanelDataSet.objects.create(
panel_data=panel_data_obj,
key=key,
value=average,
)
data.append(panel_data_obj)
return data
def generate_hourly_aggregates(self, seed=None):
self._generate_aggregate(datetime.timedelta(seconds=3600), PANEL_AGGREGATE_HOUR, seed)
def generate_daily_aggregates(self, seed=None):
self._generate_aggregate(datetime.timedelta(seconds=86400), PANEL_AGGREGATE_DAY, seed)
def get_panels(self):
"""\
Purpose is to get a queryset of panel models matching the registered
panel providers
"""
return self.filter(title__in=registry.get_titles())
def get_latest(self):
"""\
Get the latest panel data for the registered panel providers
"""
return [
PanelData.objects.minute_data().filter(panel=panel)[0] \
for panel in self.get_panels()
]
class Panel(models.Model):
title = models.CharField(max_length=255, unique=True)
slug = models.SlugField(db_index=True)
class Meta:
ordering = ('title',)
objects = PanelManager()
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Panel, self).save(*args, **kwargs)
class PanelDataManager(models.Manager):
def minute_data(self):
return self.filter(aggregate_type=PANEL_AGGREGATE_MINUTE)
def hour_data(self):
return self.filter(aggregate_type=PANEL_AGGREGATE_HOUR)
def day_data(self):
return self.filter(aggregate_type=PANEL_AGGREGATE_DAY)
def get_most_recent_update(self):
return self.minute_data().aggregate(max_date=Max('created_date'))['max_date']
class PanelData(models.Model):
"""
Preserve historical data from dashboard. Automatically deleted by the
periodic command :func:`remove_old_panel_data`
"""
panel = models.ForeignKey(Panel, related_name='data')
created_date = models.DateTimeField(db_index=True)
aggregate_type = models.IntegerField(choices=PANEL_AGGREGATE_CHOICES,
default=PANEL_AGGREGATE_MINUTE)
objects = PanelDataManager()
class Meta:
ordering = ('-created_date',)
def __unicode__(self):
return '%s: %s' % (self.panel.title, self.created_date)
def get_data(self):
data_dict = {}
for data_set in self.keys.all():
data_dict[data_set.key] = data_set.value
return data_dict
class PanelDataSet(models.Model):
panel_data = models.ForeignKey(PanelData, related_name='keys')
key = models.CharField(max_length=255)
value = models.FloatField()