I am trying to embed a plotly pie chart in a Django html template. This works fine when the chart is produced in \'online mode\' (i.e. the html snippet is stored on the plot
There's been a couple of updates to plotly, some of which are applicable here for plotly 4+:
Note: No internet connection, account, or payment is required to use plotly.py. Prior to version 4, this library could operate in either an "online" or "offline" mode. The documentation tended to emphasize the online mode, where graphs get published to the Chart Studio web service. In version 4, all "online" functionality was removed from the plotly package and is now available as the separate, optional, chart-studio package (See below). plotly.py version 4 is "offline" only, and does not include any functionality for uploading figures or data to cloud services.
This allows you to do the following to embed a graph offline:
graph = fig.to_html(full_html=False, default_height=500, default_width=700)
context = {'graph': graph}
response = render(request, 'graph.html', context)
And in graph.html
you can do:
{% if graph %}
{{ graph|safe }}
{% else %}
<p>No graph was provided.</p>
{% endif %}
Let's suppose that your piece of code that draws the graph, i.e.
from plotly.offline import download_plotlyjs, plot
import plotly.graph_objs as go
labels = [1,2,3,4]
values = [10,20,30,40]
ndata = 100
fig = {
'data': [{'labels': labels,
'values': values,
'type': 'pie',
'textposition':"none",
'textinfo':"percent",
'textfont':{'size':'12'},
'showlegend':'false'}],
'layout': {'title': 'Total:'+str(ndata),
'showlegend':'false',
'height':'200',
'width':'200',
'autosize':'false',
'margin':{'t':'50','l':'75','r':'0','b':'10'},
'separators':'.,'}
}
plotly_url = plot(fig, filename='file:///home/website/pie.html', auto_open=False)
pie_url = '''<iframe width="200" height="200" frameborder="0" seamless="seamless" scrolling="no" src=\"'''+plotly_url+'''.embed?width=200&height=200&link=false&showlegend=false\"></iframe>'''
is a funtion named graph_function()
. Inside that one, just substitute
plotly_url = plot(fig, filename='file:///home/website/pie.html', auto_open=False)
pie_url = '''<iframe width="200" height="200" frameborder="0" seamless="seamless" scrolling="no" src=\"'''+plotly_url+'''.embed?width=200&height=200&link=false&showlegend=false\"></iframe>'''
with
plt_div = plotly.offline.plot(fig, output_type='div')
return plt_div
then in your views.py:
def graph_view(request):
my_graph=graph_function()
context={'graph':my_graph}
return render(request, 'my_template.html', context_dict)
and then in your template:
{% if graph %}
{{ graph|safe }}
{% else %}
<p>No graph was provided.</p>
{% endif %}
Instead of writing the html to a file you can have plotly return the html part of the graph as a string. For example, using a class based TemplateView:
import plotly.offline as opy
import plotly.graph_objs as go
class Graph(TemplateView):
template_name = 'graph.html'
def get_context_data(self, **kwargs):
context = super(Graph, self).get_context_data(**kwargs)
x = [-2,0,4,6,7]
y = [q**2-q+3 for q in x]
trace1 = go.Scatter(x=x, y=y, marker={'color': 'red', 'symbol': 104, 'size': "10"},
mode="lines", name='1st Trace')
data=go.Data([trace1])
layout=go.Layout(title="Meine Daten", xaxis={'title':'x1'}, yaxis={'title':'x2'})
figure=go.Figure(data=data,layout=layout)
div = opy.plot(figure, auto_open=False, output_type='div')
context['graph'] = div
return context
and the template:
{% if graph %}
<div style="width:600;height:500">
{{ graph|safe }}
</div>
{% endif %}