brian_ds
brian_ds

Reputation: 367

Loading Multiple Plotly offline graphs into HTML DOM

Tools of note: Using Django 3.0, plotly offline, jQuery.

(comment after solution: solved loading plotly.offline.plot() by not including the library inside the plot div.)

I am not sure if my workflow needs changing or if there is a different DOM manipulation technique, but I am seeing slow load times while adding plots into a dashboard. The generated string elements from plots are quite large and could be a factor. (MB size if I interpret the console correctly. I am new to web design.) Basically what I think happens is the jQuery runs, and then once it returns the webpage 'freezes' while it tries to add in the DOM elements.

Okay so here is the current workflow:

  1. Load a html page with bare essentials using a Django view. Nothing fancy and this works okay.
  2. Call jQuery to run another view. This view takes a while to run a calculation and do some data manipulations which is why I tried to use jQuery. The view generates between 5-10 plotly graph_objects.
  3. Insert the images into a carousel for viewing.

Step 3 is really the step I think needs fixing if possible. If not, is there an alternative solution?

Here is my jQuery which I hope can be improved - It is found within 'script' tags inside my .html document at the end (right before the '' tag).

  var my_id = {{ my_id }}; //Django template value needed by plotly
  $( document ).ready(function() {
      var plots_id_tag = "data_plots";//data_plots is my .inner-carousel div element where everything will be inserted

      var elmt = document.getElementById(plots_id_tag);
      var endpoint = elmt.getAttribute("data-url"); //URL of view
      $.ajax({
          url: endpoint,
          data: {
              'my_id': my_id
          },

          success: function (data) {
                var is_first = true;
                var concat_divs = ''
                  //data is a JsonResponse value (serialized)
                  jQuery.each(data, function(item, val) {
                      if (is_first){
                      {#$("#" + plots_id_tag).append("<div class='item active'>" + val + "</div>");#} //Method 1 I tried was appending in loop
                      concat_divs += "<div class='item active'>" + val + "</div>" //Method two I tried was appending into a single long string.
                      is_first = false;
                      }
                      else {
                          {#$("#" + plots_id_tag).append("<div class='item'>" + val + "</div>");#}//Method 1
                          concat_divs += "<div class='item'>" + val + "</div>"//Method 2
                      }

                  })
                  $(elmt).append(concat_divs);//Method 2a
                  $(elmt).innerHTML(concat_divs);//Method 2b This one doesn't show the plots at all. I see html added to the DOM, but nothing gets shown. If this would be faster, is there an update function I need to call?


          }
      });
  })

Here is the code generation for plotly

def get_plots(df):

#Some data manip here

        layout = go.Layout(yaxis=dict(title='My plot', range=[0, y_lim], showline=True, linewidth=1, linecolor='#41b3f9', gridcolor='#e6e9ed'),
                           xaxis=dict(title=x_dim, showline=True, linewidth=1, linecolor='#41b3f9', gridcolor='#e6e9ed'),
                           title=title,
                           titlefont={'size': 18},
                           showlegend=False,
                           height=500,
                           width=1000,
                           plot_bgcolor='rgba(255,255,255,.3)')
        fig = go.Figure(data=[lower_trace, mid_trace, upper_trace], layout=layout)

        plot_conf = {'showLink': False, 'displayModeBar': False, 'responsive': True}
        div = plot(fig, auto_open=False, output_type='div', config=plot_conf)
        return div

Here is part of my view called by jQuery

        my_plots = []
        for dataframe_to_manip in list_dfs:
          my_plots.append(get_plots(dataframe_to_manip)) #long process

        return JsonResponse(my_plots, safe=False) #list of div elements generated by plotly

If you need anything else let me know, but I think that gives a descent idea what is going on. Goal - speed performance of the insertion of a number of plotly graph_objects for a dynamical dashboard. I imagine if I can shrink down the size of the plot images that might help. So if you have suggestions there as well, that is fine.

Upvotes: 1

Views: 1120

Answers (1)

brian_ds
brian_ds

Reputation: 367

Just in case someone runs across this. It appears that plotly.offline.plot() includes by default the entire plot.ly.js library. So each plot had a copy of the library inside making my html very large (MB sized)

To shrink what needed to be loaded, it is better to use: plotly.offline.plot(..., include_plotlyjs=False)

And inside your html (before your charts are generate in the html document - so maybe at the top) you put this line:

<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>

This sped up the load time from seconds to almost instant.

There may be a jQuery/js solution, but the above worked for me.

Upvotes: 1

Related Questions