Last active
December 17, 2015 16:19
-
-
Save flibbertigibbet/5637627 to your computer and use it in GitHub Desktop.
Helper functions to use the Google Visualization API in Django. Module stores queries to use and creates a JSon representation of a Google Visualization DataTable for each by inspecting the query's model. Looks up any choices defined for the columns.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import gviz_api | |
from django.db.models.query import ValuesQuerySet | |
# mapping of model field types to google vizualization column types (all not | |
# in list are 'string' type) valid google viz data types are: 'string' | |
# 'number' 'boolean' 'date' 'datetime' 'timeofday' | |
fieldmap = {'DateField':'date','DateTimeField':'datetime','BooleanField':'boolean', | |
'IntegerField':'number','DecimalField':'number','BigIntegerField':'number', | |
'FloatField':'number','TimeField':'timeofday','NullBooleanField':'boolean'} | |
# { 'queryname' : [query object, { field_name : (datatype, descriptive_name) }, | |
# { name of field with choices : { choices } }] } | |
queries = {} | |
def add_query(qry, qryName, makeStr=set()): | |
"""Takes a Django QuerySet or ValuesQuerySet and an (arbitrary, unique) name for it, | |
and adds it to the collection of queries to use in Google Visualization DataTables. Also | |
takes an optional third argument of a set of column names to be put in the DataTable as | |
strings, ignoring their data type in the model.""" | |
if type(qry) is ValuesQuerySet: | |
add_values_qry(qry, qryName, makeStr) | |
else: | |
add_full_qry(qry, qryName, makeStr) | |
def get_viz_json(qryName): | |
"""Takes a previously added query name and returns JSon representation of a | |
Google Visualization DataTable.""" | |
tbl = gviz_api.DataTable(queries[qryName][1]) | |
if type(queries[qryName][0]) is ValuesQuerySet: | |
tbl.LoadData(get_viz_data_values(qryName)) | |
else: | |
tbl.LoadData(get_viz_data_full(qryName)) | |
json = tbl.ToJSon() | |
return json | |
def add_values_qry(qry, qryName, makeStr): | |
model = qry.model | |
desc = {} # { field_name : (datatype, descriptive_name) } | |
choices = {} | |
flds = qry.field_names | |
for f in flds: | |
fld = model._meta.get_field(f) | |
t = fld.get_internal_type() # returns Django model field type as string | |
gt = 'string' # default to string type | |
if (not f in makeStr) and fieldmap.has_key(t): | |
gt = fieldmap[t] | |
if fld.choices: | |
choices[f] = dict(fld.choices) | |
desc[f] = ('string', fld.verbose_name) | |
else: | |
desc[f] = (gt, fld.verbose_name) | |
if qry.aggregate_names: | |
flds_agg = qry.aggregate_names # if query has annotations, add them as 'number' type | |
for fa in flds_agg: | |
descriptive_name = fa.replace('_', ' ') | |
desc[fa] = ('number', descriptive_name) | |
queries[qryName] = [qry, desc, choices] | |
def add_full_qry(qry, qryName, makeStr): | |
model = qry.model | |
desc = {} # { field_name : (datatype, descriptive_name) } | |
choices = {} | |
model_name = model.__name__ | |
flds = model._meta.get_all_field_names() | |
for f in flds: | |
try: | |
fld = model._meta.get_field(f) | |
except: | |
continue # in case of FK field | |
t = fld.get_internal_type() # returns Django model field type as string | |
if t == 'ForeignKey': | |
continue | |
gt = 'string' # default to string | |
if (not f in makeStr) and fieldmap.has_key(t): | |
gt = fieldmap[t] | |
desc[f] = (gt, fld.verbose_name) | |
if fld.choices: | |
choices[f] = dict(fld.choices) | |
desc[f] = ('string', fld.verbose_name) | |
else: | |
desc[f] = (gt, fld.verbose_name) | |
try: | |
flds_agg = qry.query.aggregates.keys() | |
for fa in flds_agg: | |
descriptive_name = fa.replace('_', ' ') | |
desc[fa] = ('number', descriptive_name) | |
except: | |
pass | |
queries[qryName] = [qry, desc, choices] | |
def get_viz_data_full(qryName): | |
"""Takes a QuerySet name and returns a dataset to load into a Google Visualization DataTable.""" | |
data = [] | |
qry = queries[qryName][0] | |
qry.update() # force query to re-evaluate | |
flds = queries[qryName][1].keys() | |
choices = queries[qryName][2] | |
for itm in qry: | |
row = {} | |
for fld in flds: | |
if choices.has_key(fld): | |
row[fld] = choices[fld][itm.__getattribute__(fld)] | |
else: | |
row[fld] = itm.__getattribute__(fld) | |
data.append(row) | |
return data | |
def get_viz_data_values(qryName): | |
"""Takes a ValuesQuerySet name and returns a dataset to load into a Google Visualization DataTable.""" | |
data = [] | |
qry = queries[qryName][0] | |
qry.update() # force query to re-evaluate | |
flds = queries[qryName][1].keys() | |
choices = queries[qryName][2] | |
for itm in qry: | |
row = {} | |
for fld in flds: | |
if choices.has_key(fld): | |
row[fld] = choices[fld][itm[fld]] | |
else: | |
row[fld] = itm[fld] | |
data.append(row) | |
return data | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
To use, define the queries to use with the Visualization API at the head of views.py with:
add_query(queryset, 'query name')
then in view functions, get the JSon representation of a Google Visualization DataTable for the query with:
my_json = get_viz_json('query name')
Within the HTML template, pipe the JSon through safe:
var dataTable = new google.visualization.DataTable( {{ my_json|safe }} );