• Home
  • Work
    • Programming
    • CI
  • 0 Blog
    • Login
  • About
  • Contact

Visualizing Data With Python

Plotly Dash for Django

Using the Dash libraries by Plotly to create data visualizations programmed completely in Python, and incorporating them into a Django project.

By Tabre

Dec. 23, 2017, 10:20 p.m.

The (relatively) new Dash library by Plotly offers a way to create feature-rich data visualization and analysis tools completely in Python. This is useful for those of us who prefer the Python language, and and would like to create visualizations without having to switch languages, to, say, Javascript. However, as a newer library, Dash currently offers no official way to incorporate it's projects into Django. Obviously, the ultimate solution for Django developers would be the ability to create a Dash app and incorporate it into a Django project with a simple template tag (which I’m not even sure is possible). The purpose of this blog entry is to document what I've learned about Dash and it's incorporation into Django using the tools currently available to us, in the few days since I've discovered it. 

The best method I was able to find to achieve this goal was created by the user ead on the  plotly forums at:
https://community.plot.ly/t/embed-dash-plot-into-web-page/5337/3

Check out the repository for the project at:
https://bitbucket.org/m_c_/sample-dash

For my purposes, I've tweaked the code slightly to work with Django 2.0 since that is what I'm running on this server, and also Python 3.6. The solution is actually quite simple and elegant for a work-around.

In order to resolve Dash urls through Django we need two entries to our urlpatterns in urls.py. Note I am using the application name chart for my Dash app:

from chart import views as chartviews

urlpatterns=[
     path('dash-', chartviews.dash),
     path('_dash-', chartviews.dash_ajax),
]
Copy


Next, let's take a look at the views.py. Essentially, all we are doing is handing off the request to the dispatcher function from the as_dash.py file:

from chart.as_dash import dispatcher

def dash(request, **kwargs):
     ''' '''
     return HttpResponse(dispatcher(request))

@csrf_exempt
def dash_ajax(request,**kwargs):
     ''' '''
     return HttpResponse(dispatcher(request), content_type='application/json')
Copy


Now for the Dash project itself.  I used the original project from the sample-dash repository, but also, as an exercise to help me learn Dash, I recreated the simple demonstration project coded by Chris Parmer (chriddyp) at Plotcon 2016 in this video:



Please note that the code used in the video is no longer working because it was Dash pre-release. 

In order to make this work, you can use syntax similar to my as-dash.py  (where, for our purposes, the entirety of the Dash project is defined). Also, note that we can think of our functions in this file as being akin to views in Django and each of these "views" for Dash must start with "dash_"  so that it can be recognized and loaded by the dispatcher (here, we use dash_index, dash_fig1,  dash_fig2, and dash_stockchart). The URLs are the same but with the “_” replaced with “-“.

import sys
from random import randint

import dash
import dash_core_components as dcc
import dash_html_components as dhc

import pandas_datareader as pdr

def dispatcher(request):
     '''
     Main function
     @param request: Request object
     '''

     app = create_app()
     params = {
          'data': request.body,
          'method': request.method,
          'content_type': request.content_type
     }
     with app.server.test_request_context(request.path, **params):
          app.server.preprocess_request()
          try;
               response = app.server.full_dispatch_request()
          except Exception as e:
               response = app.server.make_response(app.server.handle_exception(e))
          return response.get_data()

def _create_app():
     '''Creates dash application'''

     app = dash.Dash(csrf_protect=False)
     app.config['suppress_callback_exceptions']=True
     app.layout = dhc.Div(children=[
          dcc.Location(id='url', refresh=False),
          dhc.A('Home', href='/dash-index'),
          ',',
          dhc.A('Figure 1', href='/dash-fig1'),
          ',',
          dhc.A('Figure 2', href='/dash-fig2'),
          ',',
          dhc.A('Stock Chart', href='/dash-stockchart'),
          dhc.Br(),
          dhc.Br(),
          dhc.Div(id='content')
     ])

     @app.callback(
          dash.dependencies.Output('my-graph', 'figure'),
          [dash.dependencies.Input('my-input', 'value')]
     )
     def update_graph(value):

          df = pdr.get_data_yahoo(value)

          figure = {
               'data': [{
                    'name': 'Some name',
                    'mode': 'scatter',
                    'line': {
                         'color': 'rgb(0,0,255)',
                         'opacity': 1
                    },
                    'type': 'scatter',
                    'x': df.index,
                    'y': df.Open,
               }],
               'layout;: {
                    'autosize': True,
                    'scene': {
                         'bgcolor': 'rgb(0,0,0)'},
                         'xaxis': {
                              'titlefont': {'color': 'rgb(0,0,0)'},
                              'title': 'X-AXIS',
                              'color': 'rgb(0,0,0)'
                         },
                         'yaxis': {
                              'titlefont': {'color': 'rgb(0,0,0)'},
                              'title': 'Y-AXIS',
                              'color': 'rgb(0,0,0)'
                         }
                    }
               }
          }
          return figure

     @app.callback(
          dash.dependencies.Output('content', 'children'),
          [dash.dependencies.Input('url', 'pathname')]
     )
     def display_page(pathname):
          '''  '''
          if not pathname:
               return ''
          if pathname =='/':
               return dash_index()
          method = pathname[1:].replace('-', '_')
          func = getattr(sys.modules[__name__], method, None)
          if func:
               return func()
     return app

def dash_index():
     ''' '''
     return 'Dash Home Page'

def dash_fig1():
     ''' '''
     return dcc.Graph(
          id='main-graph',
          figure={
               'data': [{
                    'name': 'Some name',
                    'mode': 'scatter',
                    'line': {
                         'color': 'rgb(0,0,0)',
                         'opacity': 1
                    },
                    'type': 'bar',
                    'x': [x for x in range(0, 30)],
                    'y': [randint(1, 100) for x in range(0, 20)]
               }],
               'layout': {
                    'autosize': True,
                    'width': 800,
                    'height': 500,
                    'plot_bgcolor': 'rgb(150,150,150)',
                    'paper_bgcolor': 'rgb(200,200,200)',
                    'scene': {
                         'bgcolor': 'rgb(255,255,255)',
                         'xaxis': {
                              'titlefont': {'color': 'rgb(0,0,0)'},
                              'title': 'X-AXIS',
                              'color': 'rgb(0,0,0)'
                         },
                         'yaxis': {
                              'titlefont': {'color': 'rgb(0,0,0)'},
                              'title': 'Y-AXIS',
                              'color': 'rgb(0,0,0)'
                         }
                    }
               }
          }
     )

def dash_fig2():
     ''' '''
     return dcc.Graph(
          id='main-graph',
          figure={
               'data': [{
                    'name': 'Some name',
                    'mode': 'scatter',
                    'line'; {
                         'color': 'rgb(0,0,255)',
                         'opacity': 1
                    },
                    'type': 'scatter',
                    'x': [x for x in range(0, 20)],
                    'y': [randint(1, 100) for x in range(0, 20)]
               }],
               'layout': {
                    'autosize': True,
                    'scene': {
                         'bgcolor': 'rgb(175,175,175)',
                         'xaxis': {
                              'titlefont': {'color': 'rgb(0,0,0)'},
                              'title': 'X-AXIS',
                              'color': 'rgb(0,0,0)'
                         },
                         'yaxis': {
                              'titlefont': {'color': 'rgb(0,0,0)'},
                              'title': 'Y-AXIS',
                              'color': 'rgb(0,0,0)'
                         }
                    }
               }
          }
     )

def dash_stockchart():
     ''' '''
     df = pdr.get_data_yahoo('BRK-A')

     children = [
          dhc.H1('Stock Chart'),
          dcc.Dropdown(
               id='my-input',
               options=[
                    {'label': 'Berkshire Hathaway A', 'value': 'BRK-A'},
                    {'label': 'Berkshire Hathaway B', 'value': 'BRK-B'},
                    {'label': 'Fiat Chrysler', 'value': 'FCAU'},
                    {'label': 'Ford', 'value': 'F'},
                    {'label': 'Apple', 'value': 'AAPL'},
                    {'label': 'Amazon', 'value': 'AMZN'},
                    {'label': 'Coke', 'value': 'COKE'},
                    {'label': 'Tesla', 'value': 'TSLA'},
               ],
               value='BRK-A',
           ),
           dcc.Graph(
                id='my-graph',
                figure={
                     'data': [{
                          'name': 'Some name',
                          'mode': 'scatter',
                          'line': {
                               'color': 'rgb(0,0,255)',
                               'opacity': 1
                          },
                          'type': 'scatter',
                          'x': df.index,
                          'y': df.Open,
                     }],
                     'layout': {
                          'autosize': True,
                          'scene': {
                               'bgcolor': 'rgb(175,175,175)',
                               'xaxis': {
                                    'titlefont': {'color': 'rgb(0,0,0)'},
                                    'title': 'X-AXIS',
                                    'color': 'rgb(0,0,0)'
                               },
                               'yaxis': {
                                    'titlefont': {'color': 'rgb(0,0,0)'},
                                    'title': 'Y-AXIS',
                                    'color': 'rgb(0,0,0)'
                               }
                          }
                     }
                }
           )
      ]
      return children

if __name__ == '__main__':
     app = _create_app()
     app.run_server()



This app will use pandas to connect to Yahoo Finance, pull stock data, and plot it on a Plotly line chart. Check out the end result here:

https://tabre.com/dash-stockchart




Add Comment

Comments:

No Comments.

About tabre.com

This site was built with Python 3.6 and Django 2.0 running on Ubuntu 16.04 with Gunicorn, Nginx, PostgreSQL, and MongoDB.

Latest Posts

  • Defcad Guns
  • Project Brutality - Silent Protagonist
  • Visualizing Data With Python
  • ASUS PCE-AC88 Wifi on Ubuntu
  • Lean Six Sigma

Links

  • Home
  • Work
  • Blog
  • About us
  • Contact

Contact Information

  • tabre@tabre.com
  • tabre.com

© 2017 Tabre Perez. All Rights Reserved.