def __init__(self, user, *args, **kwargs): self.report_id = None if 'report_id' in kwargs: self.report_id = kwargs.pop('report_id') if 'chart_id' in kwargs: self.chart_id = kwargs.pop('chart_id') chart = get_object_or_404(Chart, pk=self.chart_id) self.report_id = chart.report_id super(ChartForm, self).__init__(*args, **kwargs) if not self.report_id: return report = get_object_or_404(Report, pk=self.report_id) chart = None if hasattr(self, 'chart_id'): chart = get_object_or_404(Chart, pk=self.chart_id) model = loads(report.model) object = model.name object = object.split('.') module_name = object[0] + '.' + object[1] + '.' + object[2] import_name = object[3] module = __import__(module_name, globals(), locals(), [import_name], -1) classobj = getattr(module, import_name) unfiltered_set = classobj.objects.exclude(trash=True) set = [] for s in unfiltered_set: filtered = False for field in model.fields: if field.filters and str(getattr( s, field.name)) not in field.filters: filtered = True if not filtered: set.append(s) # perhaps do type checking on a setting list of types (for each type) self.fields['grouping'].choices = [('', '--------')] # Check for group groupname = None groups = None for field in model.fields: self.fields['grouping'].choices.append( (str(field.name), str(field.name).replace('_', ' ').title())) if field.groupby == 1: self.fields['grouping'].initial = str(field.name) if chart: options = loads(chart.options) for f in options: if f in self.fields: self.fields[f].initial = options[f]
def __init__(self, user, *args, **kwargs): self.report_id = None if 'report_id' in kwargs: self.report_id = kwargs.pop('report_id') if 'chart_id' in kwargs: self.chart_id = kwargs.pop('chart_id') chart = get_object_or_404(Chart, pk=self.chart_id) self.report_id = chart.report_id super(ChartForm, self).__init__(*args, **kwargs) if not self.report_id: return report = get_object_or_404(Report, pk=self.report_id) chart = None if hasattr(self, 'chart_id'): chart = get_object_or_404(Chart, pk=self.chart_id) model = loads(report.model) object = model.name object = object.split('.') module_name = object[0] + '.' + object[1] + '.' + object[2] import_name = object[3] module = __import__( module_name, globals(), locals(), [import_name], -1) classobj = getattr(module, import_name) unfiltered_set = classobj.objects.exclude(trash=True) set = [] for s in unfiltered_set: filtered = False for field in model.fields: if field.filters and str(getattr(s, field.name)) not in field.filters: filtered = True if not filtered: set.append(s) # perhaps do type checking on a setting list of types (for each type) self.fields['grouping'].choices = [('', '--------')] # Check for group groupname = None groups = None for field in model.fields: self.fields['grouping'].choices.append( (str(field.name), str(field.name).replace('_', ' ').title())) if field.groupby == 1: self.fields['grouping'].initial = str(field.name) if chart: options = loads(chart.options) for f in options: if f in self.fields: self.fields[f].initial = options[f]
def report_group(request, report_id, field_name, response_format='html'): "View to Group by a given field in a report" t = get_object_or_404(Report, pk=report_id) if not request.user.get_profile().has_permission(t, mode='w'): return user_denied(request, message="You don't have access to this Report") model = loads(t.model) # Check if this field is already grouped, if so then remove grouping thisfield = model.get_field(field_name) if thisfield.groupby == 1: thisfield.groupby = 0 else: # Other wise reset grouping and set selected field as groupfield for field in model.fields: field.groupby = 0 field = model.get_field(field_name) field.groupby = 1 t.model = dumps(model) t.save() return report_edit(request, report_id=report_id, response_format=response_format)
def is_field_number(report, field_name): model = loads(report.model) classobj = model.get_class_object() field = classobj._meta.get_field_by_name(field_name)[0] if number_field_regex.match(field.get_internal_type()): return True return False
def report_filter_remove(request, report_id, field_name, filter_index, response_format='html'): "Remove a Filter on a given field for a Report" report = get_object_or_404(Report, pk=report_id) if not request.user.get_profile().has_permission(report, mode='w'): return user_denied(request, message="You don't have write access to this Report") model = loads(report.model) field = model.get_field(field_name) field.filters.pop(int(filter_index) - 1) report.model = dumps(model) report.save() return HttpResponseRedirect(reverse('reports_report_edit', args=[int(report_id)]))
def save(self): # add filter to field if not self.data['choice']: return t = self.report model = loads(t.model) classobj = model.get_class_object() xfield = classobj._meta.get_field_by_name(self.field_name)[0] field = model.get_field(self.field_name) if not field.filters: field.filters = [] c = self.data['choice'] type = xfield.get_internal_type() if type == 'ManyToManyField': c = xfield.related.parent_model.objects.filter(pk=c)[0] if type == 'ForeignKey': c = xfield.related.parent_model.objects.filter(pk=c)[0] display_choice = c if hasattr(self.fields['choice'], 'choices'): for choice, dc in self.fields['choice'].choices: if unicode(c) == unicode(choice): display_choice = dc break for choice, dc in self.fields['operand'].choices: if unicode(self.data['operand']) == unicode(choice): display_operand = dc break display = "%s %s %s" % (field.get_human_name(), display_operand, unicode(display_choice)) field.filters.append({ 'choice': c, 'operand': self.data['operand'], 'display': display }) t.model = dumps(model) t.save()
def report_filter_remove(request, report_id, field_name, filter_index, response_format='html'): "Remove a Filter on a given field for a Report" report = get_object_or_404(Report, pk=report_id) if not request.user.get_profile().has_permission(report, mode='w'): return user_denied( request, message="You don't have write access to this Report") model = loads(report.model) field = model.get_field(field_name) field.filters.pop(int(filter_index) - 1) report.model = dumps(model) report.save() return HttpResponseRedirect( reverse('reports_report_edit', args=[int(report_id)]))
def save(self): # add filter to field if not self.data['choice']: return t = self.report model = loads(t.model) classobj = model.get_class_object() xfield = classobj._meta.get_field_by_name(self.field_name)[0] field = model.get_field(self.field_name) if not field.filters: field.filters = [] c = self.data['choice'] type = xfield.get_internal_type() if type == 'ManyToManyField': c = xfield.related.parent_model.objects.filter(pk=c)[0] if type == 'ForeignKey': c = xfield.related.parent_model.objects.filter(pk=c)[0] display_choice = c if hasattr(self.fields['choice'], 'choices'): for choice, dc in self.fields['choice'].choices: if unicode(c) == unicode(choice): display_choice = dc break for choice, dc in self.fields['operand'].choices: if unicode(self.data['operand']) == unicode(choice): display_operand = dc break display = "%s %s %s" % ( field.get_human_name(), display_operand, unicode(display_choice)) field.filters.append({'choice': c, 'operand': self.data['operand'], 'display': display }) t.model = dumps(model) t.save()
def report_edit(request, report_id=None, response_format='html'): "Create new report based on user choice" report = get_object_or_404(Report, pk=report_id) if not request.user.get_profile().has_permission(report, mode='w'): return user_denied(request, message="You don't have access to edit this Report") model = loads(report.model) if request.POST and 'commit' in request.POST: # UPDATE MODEL if 'report_name' in request.POST: report.name = request.POST['report_name'] fieldnames = [] aggregations = {} for key in request.POST: if 'field' in key: fieldnames.append(request.POST[key]) elif 'aggregation-' in key: aggregations[key[12:]] = request.POST[key] for field in model.fields: field.aggregation = aggregations.get(field.name, None) if field.name in fieldnames: field.display = True else: field.display = False report.model = dumps(model) report.save() if 'commit' in request.POST: return HttpResponseRedirect( reverse('reports_report_view', args=[report.id])) return render_to_response('reports/report_edit', { 'report': report, 'model': model, }, context_instance=RequestContext(request), response_format=response_format)
def report_edit(request, report_id=None, response_format='html'): "Create new report based on user choice" report = get_object_or_404(Report, pk=report_id) if not request.user.get_profile().has_permission(report, mode='w'): return user_denied(request, message="You don't have access to edit this Report") model = loads(report.model) if request.POST and 'commit' in request.POST: # UPDATE MODEL if 'report_name' in request.POST: report.name = request.POST['report_name'] fieldnames = [] aggregations = {} for key in request.POST: if 'field' in key: fieldnames.append(request.POST[key]) elif 'aggregation-' in key: aggregations[key[12:]] = request.POST[key] for field in model.fields: field.aggregation = aggregations.get(field.name, None) if field.name in fieldnames: field.display = True else: field.display = False report.model = dumps(model) report.save() if 'commit' in request.POST: return HttpResponseRedirect(reverse('reports_report_view', args=[report.id])) return render_to_response('reports/report_edit', {'report': report, 'model': model, }, context_instance=RequestContext(request), response_format=response_format)
def __init__(self, user, *args, **kwargs): if not (kwargs.has_key('report') and kwargs.has_key('field_name')): return report = kwargs.pop('report') field_name = kwargs.pop('field_name') super(FilterForm, self).__init__(*args, **kwargs) model = loads(report.model) self.report = report self.field_name = field_name classobj = model.get_class_object() field = classobj._meta.get_field_by_name(field_name)[0] # TODO: Provisions for ManyToMany fields self.fields['operand'] = forms.ChoiceField() if field.get_internal_type() == 'ForeignKey': self.fields['choice'] = forms.ModelChoiceField( queryset=Object.filter_permitted( user, field.related.parent_model.objects.all(), mode='x')) fc = (('is', 'is'), ('not', 'is not')) elif field.get_internal_type() == 'DateTimeField': self.fields['choice'] = forms.DateTimeField() self.fields['choice'].widget.attrs.update( {'class': 'datetimepicker'}) fc = (('beforedatetime', 'before'), ('afterdatetime', 'after')) elif field.get_internal_type() == 'DateField': self.fields['choice'] = forms.DateField() self.fields['choice'].widget.attrs.update({'class': 'datepicker'}) fc = (('beforedate', 'before'), ('afterdate', 'after'), ('on', 'on')) else: self.fields['choice'] = field.formfield() fc = (('is', 'is'), ('not', 'is not')) self.fields['operand'].choices = fc self.fields['operand'].label = "" self.fields['choice'].label = "" self.fields['choice'].help_text = ""
def __init__(self, user, *args, **kwargs): if not (kwargs.has_key('report') and kwargs.has_key('field_name')): return report = kwargs.pop('report') field_name = kwargs.pop('field_name') super(FilterForm, self).__init__(*args, **kwargs) model = loads(report.model) self.report = report self.field_name = field_name classobj = model.get_class_object() field = classobj._meta.get_field_by_name(field_name)[0] # TODO: Provisions for ManyToMany fields self.fields['operand'] = forms.ChoiceField() if field.get_internal_type() == 'ForeignKey': self.fields['choice'] = forms.ModelChoiceField(queryset=Object.filter_permitted(user, field.related.parent_model.objects.all(), mode='x')) fc = (('is', 'is'), ('not', 'is not')) elif field.get_internal_type() == 'DateTimeField': self.fields['choice'] = forms.DateTimeField() self.fields['choice'].widget.attrs.update( {'class': 'datetimepicker'}) fc = (('beforedatetime', 'before'), ('afterdatetime', 'after')) elif field.get_internal_type() == 'DateField': self.fields['choice'] = forms.DateField() self.fields['choice'].widget.attrs.update({'class': 'datepicker'}) fc = (('beforedate', 'before'), ( 'afterdate', 'after'), ('on', 'on')) else: self.fields['choice'] = field.formfield() fc = (('is', 'is'), ('not', 'is not')) self.fields['operand'].choices = fc self.fields['operand'].label = "" self.fields['choice'].label = "" self.fields['choice'].help_text = ""
def display_chart(context, chart, skip_group=False): "Return HTML for chart" request = context['request'] response_format = 'html' if 'response_format' in context: response_format = context['response_format'] options = loads(chart.options) content = _get_report_content(chart.report, request) objs = content['set'] chart_dict = {} field_name = options['grouping'] model = loads(chart.report.model) chart_dict['yAxis'] = {'allowDecimals': False, 'title': {'text': model.name.split('.')[-1] + " Count vs. " + field_name.replace('_', ' ').title()}} chart_dict['xAxis'] = {} try: xfield = objs[0]._meta.get_field_by_name(field_name)[0] except: chart.delete() return def get_date(g, mindate): if g and g != datetime.min.date(): return g else: return mindate if xfield.get_internal_type() == 'ManyToManyField': l = [] for obj in objs: for mi in getattr(obj, field_name).all(): l.append(unicode(mi)) elif xfield.get_internal_type() == 'DateTimeField' or xfield.get_internal_type() == 'DateField': chart_dict['xAxis']['labels'] = { # 'rotation':90, 'align': 'left', 'x': 3, 'y': 15} l, m, datelist = [], [], [] maxdate = None mindate = None for obj in objs: if getattr(obj, field_name): x = getattr(obj, field_name) if xfield.get_internal_type() == 'DateTimeField': x = x.date() if not maxdate or x > maxdate: maxdate = x if not mindate or x < mindate: mindate = x datelist.append(x) if unicode(x) not in m: m.append(unicode(x)) else: datelist.append(datetime.min.date()) while datetime.min.date() in datelist: datelist.append(mindate) datelist.remove(datetime.min.date()) datelist = sorted(datelist, key=lambda g: get_date(g, mindate)) l = [unicode(g) for g in datelist] # chart_dict['xAxis']['categories']=m chart_dict['xAxis']['type'] = 'datetime' td = maxdate - mindate #print (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6 chart_dict['zoomType'] = 'x' chart_dict['xAxis']['tickInterval'] = ( td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6) / 10 ** 4 #chart_dict['xAxis']['tickWidth']= 0, chart_dict['maxZoom'] = 14 * 24 * 3600000 # 2wks #chart_dict['xAxis']['gridLineWidth']= 1, chart_dict['series'] = [{'name': model.name.split('.')[-1], 'data':[]}] for x in set(l): chart_dict['series'][0]['data'].append(('%s UTC' % x, l.count(x))) else: l = [unicode(obj.get_field_value(field_name)) for obj in objs] if not 'series' in chart_dict: chart_dict['series'] = [] #chart_dict['series'].append({'name':field_name, 'data': [{'name': x, 'y':l.count(x)} for x in set(l)]}) chart_dict['series'].append({'name': field_name.replace( '_', ' ').title(), 'data': [[x, l.count(x)] for x in set(l)]}) # for x in set(l): # chart_dict['series'].append({'name':x, 'data': l.count(x)}) #chart_dict['series'].append({'data':[{'name':x, 'y': [l.count(x)]} for x in set(l)]}) if not 'xAxis' in chart_dict: chart_dict['xAxis']['categories'] = [x for x in set(l)] # Chart type specific options if 'legend' in options and options['legend'] == 'on': chart_dict['legend'] = { 'layout': 'vertical', 'align': 'right', 'verticalAlign': 'top', 'x': -10, 'y': 100, 'borderWidth': 0 } if 'title' in options: chart_dict['title'] = {'text': options['title']} # Create a hash and use it as a unqiue div id and var name for the chart. hasher = hashlib.md5() hasher.update(str(random())) id = 'chartcontainer' + str(hasher.hexdigest()) # Disable animation for when saving as PDF chart_dict['chart'] = {'renderTo': id, 'defaultSeriesType': options['type']} #chart_dict['plotOptions'] = {'series': {'animation': False}} chart_dict['plotOptions'] = {'pie': { 'allowPointSelect': True, 'cursor': 'pointer', 'dataLabels': { 'enabled': False }, 'showInLegend': True }} chart_dict['credits'] = {'enabled': False} rendered_options = json.dumps(chart_dict) rendered_options = rendered_options[ :-1] + ", tooltip: {formatter: function() {return '<b>'+ this.point.name +'</b>: '+ this.y;}}}" if 'type' in chart_dict['xAxis'] and chart_dict['xAxis']['type'] == 'datetime': rendered_options += """ datedata = []; jQuery.each(options.series[0].data, function(i,item){ date = Date.parse(item[0]); count = item[1]; datedata.push([date, count]); }); options.series[0].data = datedata; function merge_options(obj1,obj2){ var obj3 = {}; for (attrname in obj1) { obj3[attrname] = obj1[attrname]; } for (attrname in obj2) { obj3[attrname] = obj2[attrname]; } return obj3; } var dateoptions = { tooltip: { shared: true, crosshairs: true }, }; options = merge_options(options, dateoptions); """ return Markup(render_to_string('reports/tags/chart', {'rendered_options': rendered_options, 'id': id, 'chart_id': chart.id, 'chart': chart, 'name': options['title']}, context_instance=RequestContext(request), response_format=response_format))
def _get_report_content(report, request=None): model = loads(report.model) object = model.name object = object.split('.') module_name = object[0] + '.' + object[1] + '.' + object[2] import_name = object[3] module = __import__(module_name, globals(), locals(), [import_name], -1) classobj = getattr(module, import_name) if request: unfiltered_set = Object.filter_by_request(request, classobj.objects) else: unfiltered_set = classobj.objects.exclude(trash=True) # construct filter filters = {} excludes = {} for field in model.fields: for filter in field.filters: if filter['operand'] == 'is': filters.setdefault(field.name + '__in', []).append(filter['choice']) elif filter['operand'] == 'not': excludes.setdefault(field.name + '__in', []).append(filter['choice']) elif filter['operand'] == 'beforedate': filters[field.name + '__gte'] = datetime.date( datetime.strptime(filter['choice'], '%m/%d/%Y')) elif filter['operand'] == 'afterdate': filters[field.name + '__lte'] = datetime.date( datetime.strptime(filter['choice'], '%m/%d/%Y')) elif filter['operand'] == 'beforedatetime': filters[field.name + '__gte'] = datetime.strptime( filter['choice'], '%m/%d/%Y %H:%M') elif filter['operand'] == 'afterdatetime': filters[field.name + '__lte'] = datetime.strptime( filter['choice'], '%m/%d/%Y %H:%M') elif filter['operand'] == 'on': filters.setdefault(field.name + '__in', []).append( datetime.strptime(filter['choice'], '%m/%d/%Y')) set = unfiltered_set.filter(**filters).exclude(**excludes) # Check for group groupname = None groups = None for field in model.fields: if field.groupby == 1: groupname = field.name if groupname: xfield = classobj._meta.get_field_by_name(groupname)[0] xtype = xfield.get_internal_type() if xtype == 'ManyToManyField': set = sorted( set, key=lambda item: (", ".join( [unicode(i) for i in getattr(item, groupname).all()])), reverse=True) groups, groupnames = [], [] for obj in set: for n in getattr(obj, groupname).all(): if n not in groupnames: groupnames.append(n) for n in groupnames: l = [] for obj in set: if n in getattr(obj, groupname).all(): l.append(obj) groups.append((unicode(n), l)) elif xtype == ('DateTimeField' or 'DateField'): set = set.order_by(groupname) #set = sorted(set, key = lambda item: getattr(item,groupname)) # TODO: Fix this sort groups, groupnames, l, ng = [], [], [], [] n = None if xtype == 'DateTimeField': def dt(ob): return getattr(ob, groupname).date() else: def dt(ob): return getattr(ob, groupname) for x in set: n = dt(x) if n: break if n: for obj in set: if getattr(obj, groupname): if dt(obj) == n: l.append(obj) else: groups.append((unicode(n), l)) l = [] n = dt(obj) l.append(obj) else: ng.append(obj) if ng: groups.append(('None', ng)) else: set = sorted( set, key=lambda item: unicode(item.get_field_value(groupname)), reverse=True) groups = [] for g, ks in groupby( set, key=lambda item: unicode(item.get_field_value(groupname))): groups.append((g, list(ks))) xfield = set[0]._meta.get_field_by_name(groupname)[0] # Count aggregate functions agg_funcs = {} for field in model.fields: # get fields and aggregate functions for them if field.display and getattr(field, 'aggregation', None): xfield = classobj._meta.get_field_by_name(field.name)[0] if number_field_regex.match(xfield.get_internal_type()) \ and aggregate_functions.has_key(field.aggregation): agg_funcs[field.name] = aggregate_functions[ field.aggregation]['function'] aggregations = {} if agg_funcs: for grouper, ls in groups if groups else (('set', set), ): data = {} for s in ls: for key in agg_funcs: data.setdefault(key, []).append(getattr(s, key, 0)) aggrs = {} for key, func in agg_funcs.items(): aggrs[key] = func(data.get(key, [ 0, ])) aggregations[grouper] = aggrs return { 'model': model, 'set': set, 'groups': groups, 'groupname': groupname, 'aggregations': aggregations }
def _get_report_content(report, request=None): model = loads(report.model) object = model.name object = object.split('.') module_name = object[0] + '.' + object[1] + '.' + object[2] import_name = object[3] module = __import__(module_name, globals(), locals(), [import_name], -1) classobj = getattr(module, import_name) if request: unfiltered_set = Object.filter_by_request(request, classobj.objects) else: unfiltered_set = classobj.objects.exclude(trash=True) # construct filter filters = {} excludes = {} for field in model.fields: for filter in field.filters: if filter['operand'] == 'is': filters.setdefault(field.name + '__in', []).append(filter['choice']) elif filter['operand'] == 'not': excludes.setdefault(field.name + '__in', []).append(filter['choice']) elif filter['operand'] == 'beforedate': filters[field.name + '__gte'] = datetime.date(datetime.strptime(filter['choice'], '%m/%d/%Y')) elif filter['operand'] == 'afterdate': filters[field.name + '__lte'] = datetime.date(datetime.strptime(filter['choice'], '%m/%d/%Y')) elif filter['operand'] == 'beforedatetime': filters[field.name + '__gte'] = datetime.strptime(filter['choice'], '%m/%d/%Y %H:%M') elif filter['operand'] == 'afterdatetime': filters[field.name + '__lte'] = datetime.strptime(filter['choice'], '%m/%d/%Y %H:%M') elif filter['operand'] == 'on': filters.setdefault(field.name + '__in', []).append(datetime.strptime(filter['choice'], '%m/%d/%Y')) set = unfiltered_set.filter(**filters).exclude(**excludes) # Check for group groupname = None groups = None for field in model.fields: if field.groupby == 1: groupname = field.name if groupname: xfield = classobj._meta.get_field_by_name(groupname)[0] xtype = xfield.get_internal_type() if xtype == 'ManyToManyField': set = sorted(set, key=lambda item: ( ", ".join([unicode(i) for i in getattr(item, groupname).all()])), reverse=True) groups, groupnames = [], [] for obj in set: for n in getattr(obj, groupname).all(): if n not in groupnames: groupnames.append(n) for n in groupnames: l = [] for obj in set: if n in getattr(obj, groupname).all(): l.append(obj) groups.append((unicode(n), l)) elif xtype == ('DateTimeField' or 'DateField'): set = set.order_by(groupname) #set = sorted(set, key = lambda item: getattr(item,groupname)) # TODO: Fix this sort groups, groupnames, l, ng = [], [], [], [] n = None if xtype == 'DateTimeField': def dt(ob): return getattr(ob, groupname).date() else: def dt(ob): return getattr(ob, groupname) for x in set: n = dt(x) if n: break if n: for obj in set: if getattr(obj, groupname): if dt(obj) == n: l.append(obj) else: groups.append((unicode(n), l)) l = [] n = dt(obj) l.append(obj) else: ng.append(obj) if ng: groups.append(('None', ng)) else: set = sorted(set, key=lambda item: unicode( item.get_field_value(groupname)), reverse=True) groups = [] for g, ks in groupby(set, key=lambda item: unicode(item.get_field_value(groupname))): groups.append((g, list(ks))) xfield = set[0]._meta.get_field_by_name(groupname)[0] # Count aggregate functions agg_funcs = {} for field in model.fields: # get fields and aggregate functions for them if field.display and getattr(field, 'aggregation', None): xfield = classobj._meta.get_field_by_name(field.name)[0] if number_field_regex.match(xfield.get_internal_type()) \ and aggregate_functions.has_key(field.aggregation): agg_funcs[field.name] = aggregate_functions[ field.aggregation]['function'] aggregations = {} if agg_funcs: for grouper, ls in groups if groups else (('set', set),): data = {} for s in ls: for key in agg_funcs: data.setdefault(key, []).append(getattr(s, key, 0)) aggrs = {} for key, func in agg_funcs.items(): aggrs[key] = func(data.get(key, [0, ])) aggregations[grouper] = aggrs return {'model': model, 'set': set, 'groups': groups, 'groupname': groupname, 'aggregations': aggregations}
def display_chart(context, chart, skip_group=False): "Return HTML for chart" request = context['request'] response_format = 'html' if 'response_format' in context: response_format = context['response_format'] options = loads(chart.options) content = _get_report_content(chart.report, request) objs = content['set'] chart_dict = {} field_name = options['grouping'] model = loads(chart.report.model) chart_dict['yAxis'] = { 'allowDecimals': False, 'title': { 'text': model.name.split('.')[-1] + " Count vs. " + field_name.replace('_', ' ').title() } } chart_dict['xAxis'] = {} try: xfield = objs[0]._meta.get_field_by_name(field_name)[0] except: chart.delete() return def get_date(g, mindate): if g and g != datetime.min.date(): return g else: return mindate if xfield.get_internal_type() == 'ManyToManyField': l = [] for obj in objs: for mi in getattr(obj, field_name).all(): l.append(unicode(mi)) elif xfield.get_internal_type( ) == 'DateTimeField' or xfield.get_internal_type() == 'DateField': chart_dict['xAxis']['labels'] = { #'rotation':90, 'align': 'left', 'x': 3, 'y': 15 } l, m, datelist = [], [], [] maxdate = None mindate = None for obj in objs: if getattr(obj, field_name): x = getattr(obj, field_name) if xfield.get_internal_type() == 'DateTimeField': x = x.date() if not maxdate or x > maxdate: maxdate = x if not mindate or x < mindate: mindate = x datelist.append(x) if unicode(x) not in m: m.append(unicode(x)) else: datelist.append(datetime.min.date()) while datetime.min.date() in datelist: datelist.append(mindate) datelist.remove(datetime.min.date()) datelist = sorted(datelist, key=lambda g: get_date(g, mindate)) l = [unicode(g) for g in datelist] #chart_dict['xAxis']['categories']=m chart_dict['xAxis']['type'] = 'datetime' td = maxdate - mindate #print (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6 chart_dict['zoomType'] = 'x' chart_dict['xAxis']['tickInterval'] = ( td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**4 #chart_dict['xAxis']['tickWidth']= 0, chart_dict['maxZoom'] = 14 * 24 * 3600000 #2wks #chart_dict['xAxis']['gridLineWidth']= 1, chart_dict['series'] = [{ 'name': model.name.split('.')[-1], 'data': [] }] for x in set(l): chart_dict['series'][0]['data'].append(('%s UTC' % x, l.count(x))) else: l = [unicode(obj.get_field_value(field_name)) for obj in objs] if not 'series' in chart_dict: chart_dict['series'] = [] #chart_dict['series'].append({'name':field_name, 'data': [{'name': x, 'y':l.count(x)} for x in set(l)]}) chart_dict['series'].append({ 'name': field_name.replace('_', ' ').title(), 'data': [[x, l.count(x)] for x in set(l)] }) #for x in set(l): # chart_dict['series'].append({'name':x, 'data': l.count(x)}) #chart_dict['series'].append({'data':[{'name':x, 'y': [l.count(x)]} for x in set(l)]}) if not 'xAxis' in chart_dict: chart_dict['xAxis']['categories'] = [x for x in set(l)] #Chart type specific options if 'legend' in options and options['legend'] == 'on': chart_dict['legend'] = { 'layout': 'vertical', 'align': 'right', 'verticalAlign': 'top', 'x': -10, 'y': 100, 'borderWidth': 0 } if 'title' in options: chart_dict['title'] = {'text': options['title']} #Create a hash and use it as a unqiue div id and var name for the chart. hasher = hashlib.md5() hasher.update(str(random())) id = 'chartcontainer' + str(hasher.hexdigest()) #Disable animation for when saving as PDF chart_dict['chart'] = { 'renderTo': id, 'defaultSeriesType': options['type'] } #chart_dict['plotOptions'] = {'series': {'animation': False}} chart_dict['plotOptions'] = { 'pie': { 'allowPointSelect': True, 'cursor': 'pointer', 'dataLabels': { 'enabled': False }, 'showInLegend': True } } chart_dict['credits'] = {'enabled': False} rendered_options = json.dumps(chart_dict) rendered_options = rendered_options[:-1] + ", tooltip: {formatter: function() {return '<b>'+ this.point.name +'</b>: '+ this.y;}}}" if 'type' in chart_dict['xAxis'] and chart_dict['xAxis'][ 'type'] == 'datetime': rendered_options += """ datedata = []; jQuery.each(options.series[0].data, function(i,item){ date = Date.parse(item[0]); count = item[1]; datedata.push([date, count]); }); options.series[0].data = datedata; function merge_options(obj1,obj2){ var obj3 = {}; for (attrname in obj1) { obj3[attrname] = obj1[attrname]; } for (attrname in obj2) { obj3[attrname] = obj2[attrname]; } return obj3; } var dateoptions = { tooltip: { shared: true, crosshairs: true }, }; options = merge_options(options, dateoptions); """ return Markup( render_to_string('reports/tags/chart', { 'rendered_options': rendered_options, 'id': id, 'chart_id': chart.id, 'chart': chart, 'name': options['title'] }, context_instance=RequestContext(request), response_format=response_format))