You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -13,13 +13,12 @@ developers to generate JavaScript data visualizations for their web
13
13
applications *without writing any JavaScript*. While learning a
14
14
JavaScript-based data visualization library like [d3.js](https://d3js.org/)
15
15
can be useful, it's often far easier to knock out a few lines of Python
16
-
code that get the job done.
16
+
code to get the job done.
17
17
18
-
With Bokeh we can create incredibly detailed interactive visualizations,
18
+
With Bokeh, we can create incredibly detailed interactive visualizations,
19
19
or just traditional ones like the following bar chart.
20
20
21
-
<imgsrc="/img/170526-bar-charts-bokeh-flask/chart-example-64.png"width="100%"class="technical-diagram img-rounded"style="border:1pxsolid#ccc"alt="Responsive bar chart with 64 bars.">
22
-
21
+
<imgsrc="/img/170526-bar-charts-bokeh-flask/chart-example-64.png"width="100%"class="technical-diagram img-rounded"style="border:1pxsolid#ccc"alt="Responsive Bokeh bar chart with 64 bars.">
23
22
24
23
Let's use the
25
24
[Flask](/flask.html)[web framework](/web-frameworks.html) with Bokeh to
@@ -28,8 +27,10 @@ create custom bar charts in a Python web app.
28
27
29
28
## Our Tools
30
29
This tutorial works with either [Python 2 or 3](/python-2-or-3.html),
31
-
but Python 3 is strongly recommended for new applications. In addition
32
-
to Python throughout this tutorial we will also use the following
30
+
but Python 3 is strongly recommended for new applications. I used
31
+
[Python 3.6.1](https://www.python.org/downloads/release/python-361/) while
32
+
writing this post. In addition to Python throughout this tutorial we
@@ -52,7 +53,7 @@ before running this code, take a look at
52
53
All code in this blog post is available open source under the MIT license
53
54
on GitHub under the
54
55
[bar-charts-bokeh-flask-python-3 directory of the blog-code-examples repository](https://github.com/fullstackpython/blog-code-examples).
55
-
Use the source code and abuse it as you like for your own applications.
56
+
Use and abuse the source code as you like for your own applications.
56
57
57
58
58
59
## Installing Bokeh and Flask
@@ -76,7 +77,7 @@ The command prompt will change after activating the virtualenv:
76
77
<imgsrc="/img/170526-bar-charts-bokeh-flask/activate-virtualenv.png"width="100%"class="technical-diagram img-rounded"style="border:1pxsolid#ccc"alt="Activating our Python virtual environment on the command line.">
77
78
78
79
Keep in mind that you need to activate the virtualenv in every new terminal
79
-
window that you want this virtualenv to be used for your project.
80
+
window where you want to use the virtualenv to run the project.
80
81
81
82
Bokeh and Flask are installable into the now-activated virtualenv
82
83
using pip. Run this command to get the appropriate Bokeh and Flask
@@ -107,8 +108,8 @@ Now we can start building our web application.
107
108
We are going to first code a basic Flask application then add our bar
108
109
chart to the rendered page.
109
110
110
-
111
-
`app.py`:
111
+
Create a folder for your project then within it create a file named
112
+
`app.py` with the following initial contents:
112
113
113
114
```python
114
115
from flask import Flask, render_template
@@ -128,11 +129,25 @@ if __name__ == "__main__":
128
129
app.run(debug=True)
129
130
```
130
131
131
-
...explain code...
132
-
133
-
`templates/chart.html`:
134
-
135
-
```
132
+
The above code is a short one-route [Flask](/flask.html) application
133
+
that defines the `chart` function. `chart` takes in an arbitrary integer
134
+
as input which will later be used to define how much data we want in our
135
+
bar chart. The `render_template` function within `chart` will use a template
136
+
from Flask's default [template engine](/template-engines.html) named
137
+
[Jinja2](/jinja2.html) to output HTML.
138
+
139
+
The last two lines in the allow us to run the Flask application from the
140
+
command line on port 5000 in debug mode. Never use debug mode for production,
141
+
that's what [WSGI servers](/wsgi-servers.html) like
142
+
[Gunicorn](/green-unicorn-gunicorn.html) are built for.
143
+
144
+
Create a subdirectory within your project folder named `templates`. Within
145
+
`templates` create a file name `chart.html`. `chart.html` was referenced in
146
+
the `chart` function of our `app.py` file so we need to create it before our
147
+
app will run properly. Populate `chart.html` with the following
148
+
[Jinja2](/jinja2.html) markup.
149
+
150
+
```jinja2
136
151
<!DOCTYPE html>
137
152
<html>
138
153
<head>
@@ -144,25 +159,242 @@ if __name__ == "__main__":
144
159
</html>
145
160
```
146
161
147
-
Short explanation of above HTML.
162
+
`chart.html`'s boilerplate displays the number of bars passed into the
163
+
`chart` function via the URL.
164
+
165
+
The `<h1>` tag's message on the number of bugs found goes along with our
166
+
sample app's theme. We will pretend to be charting the number of bugs
167
+
found by automated tests run each day.
168
+
169
+
We can test our application out now.
170
+
171
+
Make sure your virtualenv is still activated and that you are in the
172
+
base directory of your project where `app.py` is located. Run `app.py`
173
+
using the `python` command.
148
174
149
175
```
150
176
$(barchart) python app.py
151
177
```
152
178
153
-
Go to "localhost:5000" in your web browser.
179
+
Go to [localhost:5000/16/](http://localhost:5000/16/) in your web browser.
180
+
You should see a large message that changes when you modify the URL.
154
181
155
-
...Screenshots of it working...
182
+
<imgsrc="/img/170526-bar-charts-bokeh-flask/basic-app-no-chart.png"width="100%"class="technical-diagram img-rounded"style="border:1pxsolid#ccc"alt="Simple Flask app without bar chart">
183
+
184
+
Our simple Flask route is in place but that's not very exciting. Time
185
+
to add our bar chart.
156
186
157
187
158
188
## Generating the Bar Chart
189
+
We can build on the basic Flask app foundation that we just wrote with
190
+
some new Python code that uses [Bokeh](/bokeh.html).
191
+
192
+
Open `app.py` back up and change the top of the file to include the
193
+
following imports.
194
+
195
+
196
+
```python
197
+
import random
198
+
from bokeh.models import (HoverTool, FactorRange, Plot, LinearAxis, Grid,
199
+
Range1d)
200
+
from bokeh.models.glyphs import VBar
201
+
from bokeh.plotting import figure
202
+
from bokeh.charts import Bar
203
+
from bokeh.embed import components
204
+
from bokeh.models.sources import ColumnDataSource
205
+
from flask import Flask, render_template
206
+
```
207
+
208
+
Throughout the rest of the file we will need these Bokeh imports along
209
+
with the `random` module to generate data and our bar chart.
210
+
211
+
Our bar chart will use "software bugs found" as a theme. The data will
212
+
be randomly generated each time the page is refreshed. In a real application
213
+
you'd have a more stable and useful data source!
214
+
215
+
Continue modifying `app.py` so the section after the imports looks like
documentation open to know what your options are for customizing your
321
+
visualizations.
322
+
323
+
Alright, let's give our app a try with a simple chart of 4 bars. The
324
+
Flask app should automatically reload when you save `app.py` with the new
325
+
code but if you shut down the development server fire it back up with the
326
+
`python app.py` command.
327
+
328
+
Open your browser to [localhost:5000/4/](localhost:5000/4/).
329
+
330
+
<imgsrc="/img/170526-bar-charts-bokeh-flask/chart-example-4.png"width="100%"class="technical-diagram img-rounded"style="border:1pxsolid#ccc"alt="Responsive Bokeh bar chart with 4 bars.">
331
+
332
+
That one looks a bit sparse, so we can crank it up by 4x to 16 bars
333
+
by going to [localhost:5000/16/](localhost:5000/16/).
334
+
335
+
<imgsrc="/img/170526-bar-charts-bokeh-flask/chart-example-16.png"width="100%"class="technical-diagram img-rounded"style="border:1pxsolid#ccc"alt="Responsive Bokeh bar chart with 16 bars.">
336
+
337
+
Now another 4x to 128 bars with [localhost:5000/128/](localhost:5000/128/)...
338
+
339
+
<imgsrc="/img/170526-bar-charts-bokeh-flask/chart-example-128.png"width="100%"class="technical-diagram img-rounded"style="border:1pxsolid#ccc"alt="Responsive Bokeh bar chart with 128 bars.">
340
+
341
+
Looking good so far. But what about that hover tool to drill down into each
342
+
bar for more data? We can add the hover with just a few lines of code
343
+
in the `create_hover_tool` function.
344
+
345
+
346
+
## Adding a Hover Tool
347
+
Within `app.py` modify the `create_hover`_tool to match the following
348
+
code.
349
+
350
+
```python
351
+
defcreate_hover_tool():
352
+
"""Generates the HTML for the Bokeh's hover data tool on our graph."""
353
+
hover_html ="""
354
+
<div>
355
+
<span class="hover-tooltip">$x</span>
356
+
</div>
357
+
<div>
358
+
<span class="hover-tooltip">@bugs bugs</span>
359
+
</div>
360
+
<div>
361
+
<span class="hover-tooltip">$@costs{0.00}</span>
362
+
</div>
363
+
"""
364
+
return HoverTool(tooltips=hover_html)
365
+
```
366
+
367
+
It may look really odd to have HTML embedded within your Python application,
368
+
but that's how we specify what the hover tool should display. We use
369
+
`$x` to show the bar's x axis, `@bugs` to show the "bugs" field from our
370
+
data source, and `$@costs{0.00}` to show the "costs" field formatted as
371
+
a dollar amount with exactly 2 decimal places.
372
+
373
+
Make sure you changed `return None` to `return HoverTool(tooltips=hover_html)`
374
+
so we can see the results of our new function in the graph.
<imgsrc="/img/170526-bar-charts-bokeh-flask/chart-example-128-hover-tool.png"width="100%"class="technical-diagram img-rounded"style="border:1pxsolid#ccc"alt="Responsive Bokeh bar chart with 128 bars and showing the hover tool.">
380
+
381
+
Nice work! Try playing around with the number of bars in the URL and the
382
+
window size to see what the graph looks like under different conditions.
383
+
384
+
The chart gets crowded with more than 100 or so bars, but you can give
385
+
it a try with whatever number of bars you want. Here is what an
386
+
impractical amount of 50,000 bars looks like just for the heck of it:
387
+
388
+
<imgsrc="/img/170526-bar-charts-bokeh-flask/chart-example-50000.png"width="100%"class="technical-diagram img-rounded"style="border:1pxsolid#ccc"alt="Responsive Bokeh bar chart with 50000 bars.">
159
389
390
+
Yea, we may need to do some additional work to display more than a few
391
+
hundred bars at a time.
160
392
161
393
162
394
## What's next?
163
-
Nice work creating a nifty configurable bar chart in Bokeh! Next
164
-
up you can modify the color scheme, change the input data source or try
165
-
to create other types of charts.
395
+
You just created a nifty configurable bar chart in Bokeh. Next you can
396
+
modify the color scheme, change the input data source, try to create other
397
+
types of charts or solve how to display very large numbers of bars.
166
398
167
399
There is a lot more than Bokeh can do, so be sure to check out the
<ahref="http://bokeh.pydata.org/en/latest/" class="list-group-item smaller-item">Official Bokeh Docs {% include "blog/external-link.html" %}</a>
9
+
<ahref="https://github.com/fullstackpython/blog-code-examples/tree/master/bar-charts-bokeh-flask-python-3" class="list-group-item smaller-item">Code for this post {% include "blog/external-link.html" %}</a>
0 commit comments