Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class WidgetView(DashboardView):
- """
- Serves as a base class for widgets, which are content types of a dashboard.
- """
- def __init__(self):
- # Data columns that may be displayed
- self.data_columns = []
- self.widget = None
- def dispatch(self, request, *args, **kwargs):
- if 'slug' in self.kwargs:
- self.widget = get_object_or_404(Widget, slug=self.kwargs['slug'])
- if self.widget:
- # TODO: CRASH Gracefully
- if not self.widget.allow_anonymous:
- if not self.request.user.is_authenticated():
- # return HttpResponseRedirect('%s?next=%s' % (settings.LOGIN_URL, self.request.path))
- return redirect_to_login(self.request.path)
- self.template_name = self.widget.template.template_path
- return super(WidgetView, self).dispatch(request, *args, **kwargs)
- def get_context_data(self, **kwargs):
- """
- Loading templates and all kinds of data here
- :param kwargs:
- :return:
- """
- context = super(WidgetView, self).get_context_data(**kwargs)
- if self.request.is_ajax():
- context["extends_template"] = "dashboards/t_dashboard_widget_ajax_container.html"
- else:
- context["extends_template"] = "dashboards/t_dashboard_widget_container_tester.html"
- context["widget_id"] = self.__class__.__name__
- if self.widget:
- context['change_url'] = reverse('admin:uc_dashboards_widget_change', args=(self.widget.id,), current_app='uc_dashboards')
- context["widget"] = self.widget
- context['filter_query_string'] = "?" + self.request.META['QUERY_STRING']
- self.load_widget_data(context)
- return context
- def result_set_to_dict(self, result_set, qkeys):
- """
- This function helps to create a dictionar object out of a SQL query
- :param result_set:
- :param qkeys:
- :return:
- """
- # build dict for template:
- fdicts = []
- for row in result_set:
- i = 0
- cur_row = {}
- for key in qkeys:
- cur_row[key] = row[i]
- i = i + 1
- fdicts.append(cur_row)
- return fdicts
- def result_set_to_transposed_dict(self, result_set, columns, label_column):
- """
- Transposes a recordset for use in bar charts
- :param result_set:
- :param columns:
- :param label_column:
- :return:
- """
- result = []
- for row in result_set:
- pass
- pass
- def get_connection(self, database_key):
- """
- Returns a connection object for PTBi
- :return: The connection object
- """
- # ptbi_data
- conn = connections[database_key]
- return conn
- def load_widget_data(self, context):
- """
- Loads the data for the widget. Some widget fields must be set as follows:
- The column_names field is used to extract data from the SQL result set and convert it into a dictionary.
- Each column name will become a field. There may be additional information in column names.
- :param context:
- :return:
- """
- if self.widget:
- if self.widget.widget_type == Widget.TEXT_BLOCK:
- return
- params = []
- sql_query = self.widget.sql_query
- conn = self.get_connection(self.widget.database_key)
- if self.widget.filters:
- filters = ast.literal_eval(self.widget.filters)
- for filter in filters:
- if "[" in filter:
- # Filter names whose values will be in a list format, we append '[db_column_name]' at the end
- # the reason for having the column name is to use it as default
- # i.e. "... WHERE db_column_name IN (select distinct db_column_name) ..."
- filter_value = self.request.GET.getlist(filter[:filter.index('[')], '')
- if filter_value == '':
- sql_query = sql_query.replace("@" + filter[:filter.index('[')], "select distinct " + filter[filter.index('[')+1:filter.index(']')])
- else:
- sql_query = sql_query.replace("@" + filter[:filter.index('[')], ",".join(str(MySQLdb.string_literal(x)) for x in filter_value ))
- else:
- filter_value = self.request.GET.get(filter, '')
- sql_query = sql_query.replace("@" + filter, ""+ MySQLdb.string_literal(filter_value))
- params.append(filter_value)
- #print sql_query
- context["widget_id"] += self.widget.slug
- context["caption"] = self.widget.title
- context["extra_text"] = self.widget.sub_text
- try:
- cursor = conn.cursor()
- cursor.execute(sql_query)
- rows = cursor.fetchall()
- finally:
- #conn.close()
- pass
- if self.widget.widget_type == Widget.PIE or \
- self.widget.widget_type == Widget.PIE_2 or \
- self.widget.widget_type == Widget.TABLE or \
- self.widget.widget_type == Widget.TILES or \
- self.widget.widget_type == Widget.LINE_GRAPH or \
- self.widget.widget_type == Widget.PROGRESS_CIRCLE or \
- self.widget.widget_type == Widget.BAR_GRAPH:
- column_names = []
- for line in self.widget.data_columns.split('\n'):
- # Add entire column line to data_columns array, which is passed to template
- data_column = ast.literal_eval('{' + line + '}')
- self.data_columns.append(data_column)
- column_names.append(data_column['column_name'])
- # Convert the result set from the SQL query into a dictionary
- rows = self.result_set_to_dict(rows, column_names)
- context["rows"] = rows;
- context["data_columns"] = self.data_columns
- # Data points
- if self.widget.widget_type == Widget.PIE or \
- self.widget.widget_type == Widget.PIE_2 or \
- self.widget.widget_type == Widget.LINE_GRAPH or \
- self.widget.widget_type == Widget.BAR_GRAPH:
- labels = []
- for row in rows:
- if isinstance(row[self.widget.label_column], basestring):
- # UNICODE MAY FAIL HERE - without the str a 'u' will be added
- labels.append(str(row[self.widget.label_column]))
- else:
- labels.append("")
- context["labels"] = str(labels).replace("'", '"')
- # Data points is what will actually hold the data. For a pie, this will be an array.
- # For a line or bar chart, it will be several arrays. Therefore, everything will be
- # wrapped into an array of arrays - with only one element for pie
- datapoints = []
- legend_labels = []
- for column in self.widget.data_point_column.split('\n'):
- # create a dictionary like {'legend_label': 'number of admissions', 'column_name': 'admissions'}
- data_point_column_description = ast.literal_eval('{' + column + '}')
- if data_point_column_description.has_key('legend_label'):
- legend_labels.append(data_point_column_description['legend_label'])
- # single row with data points, for a line chart with 2 lines will have two of them
- datapoint_row = []
- for row in rows:
- datapoint_row.append(str(row[data_point_column_description['column_name']]))
- datapoints.append(str(datapoint_row).replace("'", ''))
- context["datapoints"] = datapoints
- context["legend_labels"] = legend_labels
- # This variable determines whether the "view data" command is available in the widget. Only
- # available for widgets that support it.
- context["supports_view_data"] = True if \
- self.widget.widget_type == Widget.LINE_GRAPH or \
- self.widget.widget_type == Widget.BAR_GRAPH or \
- self.widget.widget_type == Widget.PIE or \
- self.widget.widget_type == Widget.PIE_2 \
- else False
- def response_class(self, request, template, context, **response_kwargs):
- """
- We are overloading this method so that it can inject a template that is loaded with content from the database,
- if necessary. If the template is supposed to come from a template file (in the file system), nothing happens
- and we just call the super class' method.
- :param request:
- :param template:
- :param context:
- :param response_kwargs:
- :return:
- """
- if self.widget:
- if int(self.widget.template.template_source) == int(UCModels.Template.DATABASE):
- template = Template(self.widget.template.template_text)
- return super(WidgetView, self).response_class(request, template, context, **response_kwargs)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement