1

My problem

I'm creating an interactive plot in my Django app. I have created a view for a plotting template and a view that generates only the plot itself so that I can use <img src= "{% url 'ozmod:plot' %}"/> to render the plot with the fancy plotting template.

If I navigate to the URL I've assigned to the plotting template view I see a broken image link but the navbar and everything is extended fine. If I navigate directly to the URL for just the plot, the plot is displayed fine but, of course, the navbar and everything from page.html is not extended. I have included screen grabs of my error and my code:

views.py

class PlotView(generic.TemplateView):
    template_name = 'ozmod/plot.html'

def RunOZCOT(request):
    fig = plt.figure()
    x = range(20)
    y = [i for i in range(20)]
    random.shuffle(y)
    plot = plt.plot(x,y)
    g = mpld3.fig_to_html(fig)
    return HttpResponse(g)

urls.py

app_name = 'ozmod'
urlpatterns = [
    path('', views.HomePageView.as_view(), name='home'),
    path('metfiles/', views.MetIndexView.as_view(), name='metindex'),
    path('metfiles/<int:pk>/', views.DetailView.as_view(), name='detail'),
    path('runmodel/', views.PlotView.as_view(), name = 'runmodel'),
    path('plot/', views.RunOZCOT, name = 'plot'),
]

plot.html

{% extends "ozmod/page.html" %}

{% block content %}

<img src= "{% url 'ozmod:plot' %}"/> 
<!-- http://myserver:8000/ozmod/plot/ -->

{% endblock %}

page.html ... abbreviated for clarity

{% load static %}

<!DOCTYPE html>
<head>
  <title>OZCOT interactive</title>
</head>
<body>

<ul class="nav nav-pills">
  <li class="{% if request.resolver_match.url_name == "home" %}active{% endif %}"><a href="{% url 'ozmod:home' %}">Home</a></li>
  <li class="{% if request.resolver_match.url_name == "metindex" %}active{% endif %}"><a href="{% url 'ozmod:metindex' %}">MetIndex</a></li>
  <li class="{% if request.resolver_match.url_name == "runmodel" %}active{% endif %}"><a href="{% url 'ozmod:runmodel' %}">Plot</a></li>
</ul>

<div class="container-fluid text-center">
    {% block content %}{% endblock content %}
</div>

<nav class="navbar navbar-default navbar-fixed-bottom">
        <div class="container">
            <p>This is a test</p>
        </div>
      </nav>

</body>
</html>

This is what myserver:8000/ozmod/runmodel/ looks like

enter image description here

This is what myserver:8000/ozmod/plot/ looks like

enter image description here

What's missing?

So the plot works fine but will not display when I reference the url serving that view in the main plotting template. What am I missing?


EDIT: 2018-03-23

Use <embed> not <img>.

The problem was with the use of <img> rather than <embed>. With embed the interactive features remain responsive.

Correct views.py:

{% extends "ozmod/page.html" %}

{% block content %}

<embed src="{% url 'ozmod:plot' %}" width="800" height="600">

{% endblock %}

Result:

enter image description here

Dodge
  • 3,219
  • 3
  • 19
  • 38

1 Answers1

1

I don't really understand what mpld3.fig_to_html() does - the documentation is very sparse and I don't know anything about matplotlib or mpld3 - but it seems that it is returning some kind of HTML. That can't work as the src of an image, which is expecting a single file in an image format (gif/png/jpeg etc).

You need to use matplotlib to save the plot in that format and return it in the HttpResponse. Something like (bearing in mind I don't know the library at all):

plot = plt.plot(x,y)
response = HttpResponse()
plot.savefig(response)
return response
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Thanks! I have tried that approach and can't get the syntax right, that's why I used the mpld3 library to just get something rendered. I'm going to find the exact syntax required in this case and post it as a follow up to your answer. – Dodge Mar 18 '18 at 20:42
  • Also, is it okay to use complex code to generate plots in the view.py file? I'm not sure how long or complicated a view can be or how much working code for the visuals, etc. is appropriate for the views.py file. – Dodge Mar 18 '18 at 20:45
  • Well it can be as complex as you like, but you do need to ensure it doesn't take too long to execute or the connection will likely time out. – Daniel Roseman Mar 18 '18 at 22:46