Advertisement
aonomike

WidgetView

Mar 13th, 2017
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.58 KB | None | 0 0
  1. class WidgetView(DashboardView):
  2.     """
  3.    Serves as a base class for widgets, which are content types of a dashboard.
  4.    """
  5.  
  6.     def __init__(self):
  7.         # Data columns that may be displayed
  8.         self.data_columns = []
  9.         self.widget = None
  10.  
  11.     def dispatch(self, request, *args, **kwargs):
  12.  
  13.         if 'slug' in self.kwargs:
  14.             self.widget = get_object_or_404(Widget, slug=self.kwargs['slug'])
  15.  
  16.         if self.widget:
  17.             # TODO: CRASH Gracefully
  18.             if not self.widget.allow_anonymous:
  19.                 if not self.request.user.is_authenticated():
  20.                     # return HttpResponseRedirect('%s?next=%s' % (settings.LOGIN_URL, self.request.path))
  21.                     return redirect_to_login(self.request.path)
  22.  
  23.             self.template_name = self.widget.template.template_path
  24.         return super(WidgetView, self).dispatch(request, *args, **kwargs)
  25.  
  26.     def get_context_data(self, **kwargs):
  27.         """
  28.        Loading templates and all kinds of data here
  29.        :param kwargs:
  30.        :return:
  31.        """
  32.         context = super(WidgetView, self).get_context_data(**kwargs)
  33.         if self.request.is_ajax():
  34.             context["extends_template"] = "dashboards/t_dashboard_widget_ajax_container.html"
  35.         else:
  36.             context["extends_template"] = "dashboards/t_dashboard_widget_container_tester.html"
  37.  
  38.         context["widget_id"] = self.__class__.__name__
  39.         if self.widget:
  40.             context['change_url'] = reverse('admin:uc_dashboards_widget_change', args=(self.widget.id,), current_app='uc_dashboards')
  41.  
  42.         context["widget"] = self.widget
  43.         context['filter_query_string'] = "?" + self.request.META['QUERY_STRING']
  44.         self.load_widget_data(context)
  45.  
  46.         return context
  47.  
  48.     def result_set_to_dict(self, result_set, qkeys):
  49.         """
  50.        This function helps to create a dictionar object out of a SQL query
  51.        :param result_set:
  52.        :param qkeys:
  53.        :return:
  54.        """
  55.  
  56.         # build dict for template:
  57.         fdicts = []
  58.         for row in result_set:
  59.             i = 0
  60.             cur_row = {}
  61.             for key in qkeys:
  62.                 cur_row[key] = row[i]
  63.                 i = i + 1
  64.             fdicts.append(cur_row)
  65.         return fdicts
  66.  
  67.     def result_set_to_transposed_dict(self, result_set, columns, label_column):
  68.         """
  69.        Transposes a recordset for use in bar charts
  70.        :param result_set:
  71.        :param columns:
  72.        :param label_column:
  73.        :return:
  74.        """
  75.  
  76.         result = []
  77.         for row in result_set:
  78.             pass
  79.         pass
  80.  
  81.     def get_connection(self, database_key):
  82.         """
  83.        Returns a connection object for PTBi
  84.        :return: The connection object
  85.        """
  86.  
  87.         # ptbi_data
  88.  
  89.         conn = connections[database_key]
  90.         return conn
  91.  
  92.  
  93.     def load_widget_data(self, context):
  94.         """
  95.        Loads the data for the widget. Some widget fields must be set as follows:
  96.  
  97.        The column_names field is used to extract data from the SQL result set and convert it into a dictionary.
  98.        Each column name will become a field. There may be additional information in column names.
  99.  
  100.  
  101.        :param context:
  102.        :return:
  103.        """
  104.  
  105.  
  106.         if self.widget:
  107.  
  108.             if self.widget.widget_type == Widget.TEXT_BLOCK:
  109.                 return
  110.  
  111.             params = []
  112.             sql_query = self.widget.sql_query
  113.             conn = self.get_connection(self.widget.database_key)
  114.  
  115.             if self.widget.filters:
  116.                 filters = ast.literal_eval(self.widget.filters)
  117.                 for filter in filters:
  118.                     if "[" in filter:
  119.                         # Filter names whose values will be in a list format, we append '[db_column_name]' at the end
  120.                         # the reason for having the column name is to use it as default
  121.                         # i.e. "... WHERE db_column_name IN (select distinct db_column_name) ..."
  122.                         filter_value = self.request.GET.getlist(filter[:filter.index('[')], '')
  123.                         if filter_value == '':
  124.                             sql_query = sql_query.replace("@" + filter[:filter.index('[')], "select distinct " + filter[filter.index('[')+1:filter.index(']')])
  125.                         else:
  126.                             sql_query = sql_query.replace("@" + filter[:filter.index('[')], ",".join(str(MySQLdb.string_literal(x)) for x in filter_value ))
  127.                     else:
  128.                         filter_value = self.request.GET.get(filter, '')
  129.                         sql_query = sql_query.replace("@" + filter, ""+ MySQLdb.string_literal(filter_value))
  130.                     params.append(filter_value)
  131.  
  132.             #print sql_query
  133.  
  134.             context["widget_id"] += self.widget.slug
  135.             context["caption"] = self.widget.title
  136.             context["extra_text"] = self.widget.sub_text
  137.  
  138.             try:
  139.                 cursor = conn.cursor()
  140.                 cursor.execute(sql_query)
  141.                 rows = cursor.fetchall()
  142.             finally:
  143.                 #conn.close()
  144.                 pass
  145.  
  146.  
  147.             if self.widget.widget_type == Widget.PIE or \
  148.                             self.widget.widget_type == Widget.PIE_2 or \
  149.                             self.widget.widget_type == Widget.TABLE or \
  150.                             self.widget.widget_type == Widget.TILES or \
  151.                             self.widget.widget_type == Widget.LINE_GRAPH or \
  152.                             self.widget.widget_type == Widget.PROGRESS_CIRCLE or \
  153.                             self.widget.widget_type == Widget.BAR_GRAPH:
  154.  
  155.                 column_names = []
  156.                 for line in self.widget.data_columns.split('\n'):
  157.                     # Add entire column line to data_columns array, which is passed to template
  158.                     data_column = ast.literal_eval('{' + line + '}')
  159.                     self.data_columns.append(data_column)
  160.                     column_names.append(data_column['column_name'])
  161.  
  162.                 # Convert the result set from the SQL query into a dictionary
  163.                 rows = self.result_set_to_dict(rows, column_names)
  164.                 context["rows"] = rows;
  165.                 context["data_columns"] = self.data_columns
  166.  
  167.             # Data points
  168.             if self.widget.widget_type == Widget.PIE or \
  169.                             self.widget.widget_type == Widget.PIE_2 or \
  170.                             self.widget.widget_type == Widget.LINE_GRAPH or \
  171.                             self.widget.widget_type == Widget.BAR_GRAPH:
  172.                 labels = []
  173.                 for row in rows:
  174.                     if isinstance(row[self.widget.label_column], basestring):
  175.                         # UNICODE MAY FAIL HERE - without the str a 'u' will be added
  176.                         labels.append(str(row[self.widget.label_column]))
  177.                     else:
  178.                         labels.append("")
  179.  
  180.                 context["labels"] = str(labels).replace("'", '"')
  181.  
  182.                 # Data points is what will actually hold the data. For a pie, this will be an array.
  183.                 # For a line or bar chart, it will be several arrays. Therefore, everything will be
  184.                 # wrapped into an array of arrays - with only one element for pie
  185.                 datapoints = []
  186.                 legend_labels = []
  187.                 for column in self.widget.data_point_column.split('\n'):
  188.  
  189.                     # create a dictionary like {'legend_label': 'number of admissions', 'column_name': 'admissions'}
  190.                     data_point_column_description = ast.literal_eval('{' + column + '}')
  191.                     if data_point_column_description.has_key('legend_label'):
  192.                         legend_labels.append(data_point_column_description['legend_label'])
  193.                     # single row with data points, for a line chart with 2 lines will have two of them
  194.                     datapoint_row = []
  195.                     for row in rows:
  196.                         datapoint_row.append(str(row[data_point_column_description['column_name']]))
  197.  
  198.                     datapoints.append(str(datapoint_row).replace("'", ''))
  199.                 context["datapoints"] = datapoints
  200.                 context["legend_labels"] = legend_labels
  201.  
  202.             # This variable determines whether the "view data" command is available in the widget. Only
  203.             # available for widgets that support it.
  204.             context["supports_view_data"] = True if \
  205.                 self.widget.widget_type == Widget.LINE_GRAPH or \
  206.                 self.widget.widget_type == Widget.BAR_GRAPH or \
  207.                 self.widget.widget_type == Widget.PIE or \
  208.                 self.widget.widget_type == Widget.PIE_2 \
  209.                 else False
  210.  
  211.  
  212.  
  213.     def response_class(self, request, template, context, **response_kwargs):
  214.         """
  215.        We are overloading this method so that it can inject a template that is loaded with content from the database,
  216.        if necessary. If the template is supposed to come from a template file (in the file system), nothing happens
  217.        and we just call the super class' method.
  218.        :param request:
  219.        :param template:
  220.        :param context:
  221.        :param response_kwargs:
  222.        :return:
  223.        """
  224.         if self.widget:
  225.             if int(self.widget.template.template_source) == int(UCModels.Template.DATABASE):
  226.                 template = Template(self.widget.template.template_text)
  227.  
  228.         return super(WidgetView, self).response_class(request, template, context, **response_kwargs)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement