Skip to content

Commit 354d312

Browse files
New Feature: Its now possible to define your own graphs by subclassing a new Graph() class.
1 parent 0e3ddcb commit 354d312

File tree

5 files changed

+95
-76
lines changed

5 files changed

+95
-76
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ django-bigrother.egg-info/*
66
.idea
77
*.sqlite3
88
docs/_*
9+
*.DS_Store

Diff for: bigbrother/core.py

+30-8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ def get_module_list():
1818
)
1919
return getattr(settings, 'BIGBROTHER_MODULES', default_modules)
2020

21+
def get_graph_list():
22+
"""
23+
Returns a list of the default graphs.
24+
"""
25+
default_graphs = (
26+
'bigbrother.graphs.LastWeekGraph',
27+
'bigbrother.graphs.LastMonthGraph',
28+
'bigbrother.graphs.LastYearGraph',
29+
)
30+
return getattr(settings, 'BIGBROTHER_GRAPHS', default_graphs)
2131

2232
def get_module_classes():
2333
"""
@@ -36,6 +46,22 @@ def get_module_classes():
3646
clslist.append(cls)
3747
return clslist
3848

49+
def get_graph_classes():
50+
"""
51+
Returns all the graph classes defined in settings.
52+
"""
53+
clslist = []
54+
for m in get_graph_list():
55+
modulename, attr = m.rsplit('.', 1)
56+
try:
57+
module = import_module(modulename)
58+
except ImportError:
59+
continue
60+
cls = getattr(module, attr, None)
61+
if not cls:
62+
continue
63+
clslist.append(cls)
64+
return clslist
3965

4066
def get_module_by_slug(slug):
4167
"""
@@ -65,19 +91,15 @@ class BigBrotherModule():
6591
Base class for all BigBrother modules that implements the basic skeleton required for a module.
6692
"""
6793

68-
#: The human readable display name for the module
6994
name = 'Unnamed Module'
70-
#: Flag to indicate it should be processed by the update function and store the results in the DB.
7195
write_to_db = True
72-
#: Text to be prefixed onto the display version of the module's value
7396
prefix_text = None
74-
#: Text to be suffixed onto the display version of the module's value
7597
suffix_text = None
7698
warning_low = None
7799
warning_high = None
78100
link_url = None
79-
#: The Django ORM aggregation object to be used for aggregating the data for graph data.
80101
aggregate_function = None
102+
graphs = get_graph_list()
81103

82104
def check_compatible(self):
83105
"""
@@ -115,7 +137,7 @@ def get_text(self):
115137
Returns the current value as formatted text
116138
"""
117139
return '%s%g%s' % (self.get_prefix_text(), self.get_val(), self.get_suffix_text())
118-
140+
119141
def get_slug(self):
120142
"""
121143
Returns the URL friendly slug for the module
@@ -133,7 +155,7 @@ def check_warning(self):
133155
self.warn(warningtype='low')
134156
return True
135157
return False
136-
158+
137159
def warn(self, warningtype):
138160
send_warning(module=self.__class__, warningtype=warningtype)
139161

@@ -159,7 +181,7 @@ def get_val(self):
159181
users = USER_MODEL.objects.all()
160182
return users.count()
161183

162-
184+
163185
class NewUsersTodayCount(BigBrotherModule):
164186
"""
165187
Module providing a count of new users from django.contrib.auth

Diff for: bigbrother/graphs.py

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from bigbrother.core import get_module_by_slug
2+
from bigbrother.models import ModuleStat
3+
from django.db.models import Avg
4+
from datetime import datetime, timedelta
5+
import qsstats
6+
7+
8+
class Graph():
9+
stopdate = datetime.utcnow()
10+
11+
def get_graph_data(self, slug, *args, **kwargs):
12+
module = get_module_by_slug(slug)()
13+
q = ModuleStat.objects.filter(modulename=slug)
14+
qs = qsstats.QuerySetStats(q, 'added', module.get_aggregate_function() or Avg('value'))
15+
qss = qsstats.QuerySetStats(q, 'value')
16+
data = qs.time_series(self.startdate, self.stopdate, interval=self.interval)
17+
return data
18+
19+
20+
class LineGraph(Graph):
21+
type = 'line'
22+
23+
24+
class LastWeekGraph(LineGraph):
25+
name = 'Last Week'
26+
interval = 'days'
27+
startdate = datetime.utcnow() - timedelta(weeks=1)
28+
29+
30+
class LastMonthGraph(LineGraph):
31+
name = 'Last Month'
32+
interval = 'days'
33+
startdate = datetime.utcnow() - timedelta(weeks=4)
34+
35+
36+
class LastYearGraph(LineGraph):
37+
name = 'Last Year'
38+
interval = 'weeks'
39+
startdate = datetime.utcnow() - timedelta(weeks=52)

Diff for: bigbrother/templates/bigbrother/graph.html

+11-38
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@
33
{% block content %}
44
<div id="graphcontainer">
55
<h1>{{ modulename }}</h1>
6-
<h2>Last Week</h2>
7-
<div id="week" class="graph">No Data</div>
8-
<h2>Last Month</h2>
9-
<div id="month" class="graph">No Data</div>
10-
<h2>Last Year</h2>
11-
<div id="year" class="graph">No Data</div>
6+
{% for graph in bb %}
7+
<h2>{{ graph.name }}</h2>
8+
<div id="{{ graph.name|slugify }}" class="graph">No Data</div>
9+
{% endfor %}
1210
</div>
1311
{% endblock %}
1412

@@ -19,43 +17,18 @@ <h2>Last Year</h2>
1917
<script src="{{ STATIC_URL }}js/jquery.flot.time.js"></script>
2018
<script type="text/javascript">
2119
$(function () {
22-
{% if week %}
23-
var weekdata = [{% for dt, val in week %}[(new Date("{{ dt.isoformat }}")).getTime(), {{ val|stringformat:"f" }}],{% endfor %}]
24-
$.plot($("#week"), [weekdata], {
20+
{% for graph in bb %}
21+
var data = [{% for dt, val in graph.data %}[(new Date("{{ dt.isoformat }}")).getTime(), {{ val|stringformat:"f" }}],{% endfor %}]
22+
$.plot($("#{{ graph.name|slugify }}"), [data], {
2523
points: {show:true},
2624
lines: {show:true},
2725
yaxis: {min: 0},
2826
xaxis: {mode: "time",
29-
min: (new Date("{{ firstdow.isoformat }}")).getTime(),
30-
max: (new Date("{{ lastdow.isoformat }}")).getTime()
27+
min: (new Date("{{ graph.startdate.isoformat }}")).getTime(),
28+
max: (new Date("{{ graph.stopdate.isoformat }}")).getTime()
3129
}
3230
});
33-
{% endif %}
34-
{% if month %}
35-
var monthdata = [{% for dt, val in month %}[(new Date("{{ dt.isoformat }}")).getTime(), {{ val|stringformat:"f" }}],{% endfor %}]
36-
$.plot($("#month"), [monthdata], {
37-
points: {show:true},
38-
lines: {show:true},
39-
yaxis: {min: 0},
40-
xaxis: {mode: "time",
41-
min: (new Date("{{ firstdom.isoformat }}")).getTime(),
42-
max: (new Date("{{ lastdom.isoformat }}")).getTime()
43-
}
44-
});
45-
{% endif %}
46-
{% if year %}
47-
var yeardata = [{% for dt, val in year %}[(new Date("{{ dt.isoformat }}")).getTime(), {{ val|stringformat:"f" }}],{% endfor %}]
48-
$.plot($("#year"), [yeardata], {
49-
points: {show:true},
50-
lines: {show:true},
51-
yaxis: {min: 0},
52-
xaxis: {mode: "time",
53-
min: (new Date("{{ firstdoy.isoformat }}")).getTime(),
54-
max: (new Date("{{ lastdoy.isoformat }}")).getTime()
55-
}
56-
});
57-
{% endif %}
58-
31+
{% endfor %}
5932
});
6033
</script>
61-
{% endblock %}
34+
{% endblock %}

Diff for: bigbrother/views.py

+14-30
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
from django.db.models import Avg
55
from django.conf import settings
66
import qsstats
7-
87
from bigbrother.models import ModuleStat
9-
from bigbrother.core import get_module_classes, get_module_by_slug
8+
from bigbrother.core import get_module_classes, get_graph_classes
109

1110

1211
class BigBrotherView(TemplateView):
@@ -53,39 +52,24 @@ class BigBrotherGraphView(BigBrotherView):
5352
"""
5453

5554
template_name = 'bigbrother/graph.html'
56-
week_interval = None
57-
month_interval = None
58-
year_interval = None
59-
60-
def get_week_interval(self):
61-
return self.week_interval or 'hours'
62-
63-
def get_month_interval(self):
64-
return self.month_interval or 'days'
65-
66-
def get_year_interval(self):
67-
return self.week_interval or 'weeks'
6855

6956
def get_graph_data(self):
70-
slug = self.kwargs.get('slug')
71-
module = get_module_by_slug(slug)()
72-
q = ModuleStat.objects.filter(modulename=slug)
73-
qs = qsstats.QuerySetStats(q, 'added', module.get_aggregate_function() or Avg('value'))
74-
75-
week = qs.time_series(datetime.utcnow() - timedelta(weeks=1), datetime.utcnow(), interval=self.get_week_interval())
76-
month = qs.time_series(datetime.utcnow() - timedelta(weeks=4), datetime.utcnow(), interval=self.get_month_interval())
77-
year = qs.time_series(datetime.utcnow() - timedelta(weeks=52), datetime.utcnow(), interval=self.get_year_interval())
78-
79-
return {
80-
'week': week, 'month': month, 'year': year,
81-
'lastdow': week[-1][0], 'lastdom': month[-1][0], 'lastdoy': year[-1][0],
82-
'firstdow': week[0][0], 'firstdom': month[0][0], 'firstdoy': year[0][0],
83-
'modulename': module.name,
84-
}
57+
data = []
58+
for cls in get_graph_classes():
59+
instance = cls()
60+
dataset = instance.get_graph_data(slug=self.kwargs.get('slug'))
61+
data.append({'name': instance.name,
62+
'data': dataset,
63+
'startdate': dataset[0][0],
64+
'stopdate': dataset[-1][0]})
65+
return data
8566

8667
def get_context_data(self, **kwargs):
8768
ctx = super(BigBrotherGraphView, self).get_context_data(**kwargs)
88-
ctx.update(self.get_graph_data())
69+
ctx.update({
70+
'bb': self.get_graph_data,
71+
'modulename': self.kwargs.get('slug')
72+
})
8973
return ctx
9074

9175

0 commit comments

Comments
 (0)