0
# Embedding and Integration
1
2
Functions for embedding Bokeh plots in web pages, generating standalone HTML, and integrating with web frameworks and content management systems. These functions enable seamless integration of Bokeh visualizations into existing web applications and workflows.
3
4
## Capabilities
5
6
### HTML Component Generation
7
8
Functions for generating HTML and JavaScript components that can be embedded in web pages.
9
10
```python { .api }
11
def components(plot_objects, wrap_script=True, wrap_plot_info=True):
12
"""
13
Generate HTML components for embedding plots.
14
15
Returns separate script and div elements that can be embedded
16
in existing HTML pages. This is the most flexible embedding method.
17
18
Parameters:
19
- plot_objects: Single plot/layout or sequence of plot objects
20
- wrap_script: Whether to wrap JavaScript in <script> tags
21
- wrap_plot_info: Whether to wrap plot info in JSON
22
23
Returns:
24
Tuple[str, Union[str, List[str]]]: (script, div_elements)
25
- script: JavaScript code to render the plots
26
- div_elements: HTML div element(s) as placeholder(s)
27
28
For single plot: returns (script, div_string)
29
For multiple plots: returns (script, [div1, div2, ...])
30
"""
31
32
def file_html(models, resources, title=None, template=None, template_variables=None):
33
"""
34
Generate complete standalone HTML file content.
35
36
Creates a full HTML document containing plots with all necessary
37
resources. Ideal for saving self-contained HTML files.
38
39
Parameters:
40
- models: Plot objects or layouts to include
41
- resources: Resources object specifying how to include BokehJS
42
- title: HTML document title
43
- template: Custom Jinja2 template (optional)
44
- template_variables: Variables for template rendering
45
46
Returns:
47
str: Complete HTML document as string
48
"""
49
```
50
51
### JSON Serialization
52
53
Functions for generating JSON representations of plots for custom embedding scenarios.
54
55
```python { .api }
56
def json_item(model, target=None):
57
"""
58
Generate JSON representation for embedding.
59
60
Creates a JSON object containing all plot data and configuration
61
that can be rendered by BokehJS. Useful for AJAX-based applications
62
and custom integration scenarios.
63
64
Parameters:
65
- model: Plot object or layout to serialize
66
- target: Target element ID for rendering (optional)
67
68
Returns:
69
str: JSON string containing plot specification
70
71
The JSON can be used with bokehjs.embed.embed_item() in JavaScript.
72
"""
73
```
74
75
### Dynamic Loading
76
77
Functions for dynamic plot loading and autoloading scenarios.
78
79
```python { .api }
80
def autoload_static(model, resources, script_path):
81
"""
82
Generate script for static autoloading.
83
84
Creates JavaScript that can be included via <script> tag to
85
automatically load and render a plot. The plot data is embedded
86
in the script itself.
87
88
Parameters:
89
- model: Plot object or layout to embed
90
- resources: Resources object for BokehJS inclusion
91
- script_path: Path where the script will be served
92
93
Returns:
94
str: JavaScript code for autoloading the plot
95
96
Usage: Save returned script to a .js file and include via:
97
<script src="path/to/generated/script.js"></script>
98
"""
99
100
def autoload_server(model, app_path, server_id=None,
101
server_url="http://localhost:5006", **kwargs):
102
"""
103
Generate script for server-based autoloading.
104
105
Creates JavaScript that loads plots from a running Bokeh server.
106
Enables embedding of server applications in external websites.
107
108
Parameters:
109
- model: Plot object or layout (unused, kept for compatibility)
110
- app_path: Path to server application
111
- server_id: Server session ID (optional)
112
- server_url: URL of Bokeh server
113
114
Returns:
115
str: JavaScript code for loading from server
116
"""
117
```
118
119
### Server Document Embedding
120
121
Functions for embedding server-based applications.
122
123
```python { .api }
124
def server_document(url, relative_urls=False, resources=None, **kwargs):
125
"""
126
Embed server document in existing page.
127
128
Generates HTML/JavaScript to embed a live server application
129
document in an existing webpage with bidirectional communication.
130
131
Parameters:
132
- url: URL to server application
133
- relative_urls: Whether to use relative URLs
134
- resources: Resources object (optional)
135
136
Returns:
137
str: HTML/JavaScript for embedding server document
138
"""
139
140
def server_session(model_or_server_id, session_id=None, url=None):
141
"""
142
Embed specific server session.
143
144
Embeds a specific server session, allowing multiple sessions
145
of the same application to be embedded independently.
146
147
Parameters:
148
- model_or_server_id: Model object or server session ID
149
- session_id: Specific session ID to embed
150
- url: Server URL
151
152
Returns:
153
str: HTML/JavaScript for embedding server session
154
"""
155
```
156
157
### Resources Management
158
159
Classes for controlling how BokehJS resources are included in embedded content.
160
161
```python { .api }
162
class Resources:
163
"""
164
Controls how BokehJS resources are included.
165
166
Manages the inclusion of BokehJS JavaScript and CSS files
167
in generated HTML. Supports various deployment scenarios.
168
"""
169
def __init__(self, mode='inline', version=None, root_dir=None,
170
minified=True, log_level='info', root_url=None,
171
path_versioner=None):
172
"""
173
Parameters:
174
- mode: Resource inclusion mode
175
'inline' - Include resources directly in HTML
176
'cdn' - Link to CDN-hosted resources
177
'server' - Link to local server resources
178
'server-dev' - Link to development server resources
179
- version: Specific Bokeh version for CDN mode
180
- root_dir: Root directory for relative paths
181
- minified: Use minified JavaScript files
182
- log_level: JavaScript logging level ('trace', 'debug', 'info', 'warn', 'error', 'fatal')
183
- root_url: Base URL for server mode
184
- path_versioner: Function to add version info to paths
185
"""
186
187
mode: str
188
version: Optional[str]
189
minified: bool
190
191
# Resource URL generation
192
def js_files(self):
193
"""Get list of JavaScript file URLs."""
194
195
def css_files(self):
196
"""Get list of CSS file URLs."""
197
198
def js_raw(self):
199
"""Get raw JavaScript content (inline mode only)."""
200
201
def css_raw(self):
202
"""Get raw CSS content (inline mode only)."""
203
204
# Pre-configured resource instances
205
CDN: Resources # CDN-hosted resources (default)
206
INLINE: Resources # Inline resources (self-contained)
207
```
208
209
### Render Root
210
211
Class for advanced embedding scenarios with custom rendering containers.
212
213
```python { .api }
214
class RenderRoot:
215
"""
216
Root rendering container for embedding.
217
218
Provides fine-grained control over how plots are rendered
219
and embedded in custom containers.
220
"""
221
def __init__(self, elementid, child):
222
"""
223
Parameters:
224
- elementid: HTML element ID for rendering target
225
- child: Plot object or layout to render
226
"""
227
228
elementid: str
229
child: Model
230
```
231
232
## Usage Examples
233
234
### Basic HTML Embedding
235
236
```python
237
from bokeh.plotting import figure
238
from bokeh.embed import components
239
from bokeh.resources import CDN
240
import numpy as np
241
242
# Create plot
243
p = figure(width=400, height=400, title="Embedded Plot")
244
x = np.linspace(0, 4*np.pi, 100)
245
p.line(x, np.sin(x), line_width=2)
246
247
# Generate components
248
script, div = components(p)
249
250
# Create HTML page
251
html_template = f"""
252
<!DOCTYPE html>
253
<html lang="en">
254
<head>
255
<meta charset="utf-8">
256
<title>My Dashboard</title>
257
{CDN.render_css()}
258
{CDN.render_js()}
259
</head>
260
<body>
261
<h1>My Custom Dashboard</h1>
262
<div class="plot-container">
263
{div}
264
</div>
265
<p>This plot is embedded in custom HTML.</p>
266
{script}
267
</body>
268
</html>
269
"""
270
271
# Save HTML file
272
with open("embedded_plot.html", "w") as f:
273
f.write(html_template)
274
```
275
276
### Multiple Plots Embedding
277
278
```python
279
from bokeh.plotting import figure
280
from bokeh.embed import components
281
from bokeh.resources import CDN
282
import numpy as np
283
284
# Create multiple plots
285
plots = []
286
functions = [np.sin, np.cos, np.tan]
287
colors = ['blue', 'red', 'green']
288
289
for i, (func, color) in enumerate(zip(functions, colors)):
290
p = figure(width=300, height=300, title=f"Plot {i+1}")
291
x = np.linspace(0, 4*np.pi, 100)
292
y = func(x)
293
if func == np.tan:
294
y = np.clip(y, -5, 5) # Limit tan values
295
p.line(x, y, color=color, line_width=2)
296
plots.append(p)
297
298
# Generate components for all plots
299
script, divs = components(plots)
300
301
# Create HTML with multiple plots
302
html = f"""
303
<!DOCTYPE html>
304
<html>
305
<head>
306
<title>Multiple Plots</title>
307
{CDN.render_css()}
308
{CDN.render_js()}
309
<style>
310
.plot-grid {{
311
display: grid;
312
grid-template-columns: repeat(3, 1fr);
313
gap: 20px;
314
padding: 20px;
315
}}
316
</style>
317
</head>
318
<body>
319
<h1>Function Comparison</h1>
320
<div class="plot-grid">
321
{divs[0]}
322
{divs[1]}
323
{divs[2]}
324
</div>
325
{script}
326
</body>
327
</html>
328
"""
329
330
with open("multiple_plots.html", "w") as f:
331
f.write(html)
332
```
333
334
### JSON Embedding for AJAX
335
336
```python
337
from bokeh.plotting import figure
338
from bokeh.embed import json_item
339
import json
340
import numpy as np
341
342
# Create plot
343
p = figure(width=500, height=400, title="AJAX Plot")
344
x = np.random.random(100)
345
y = np.random.random(100)
346
p.circle(x, y, size=10, alpha=0.6)
347
348
# Generate JSON
349
plot_json = json_item(p, "myplot")
350
351
# JavaScript for AJAX loading
352
js_code = f"""
353
// JavaScript code for embedding via AJAX
354
fetch('/api/plot-data')
355
.then(response => response.json())
356
.then(item => {{
357
Bokeh.embed.embed_item(item);
358
}});
359
360
// Or directly embed the JSON item:
361
const plotItem = {plot_json};
362
Bokeh.embed.embed_item(plotItem);
363
"""
364
365
# HTML template for AJAX embedding
366
html = """
367
<!DOCTYPE html>
368
<html>
369
<head>
370
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-3.0.0.min.js"></script>
371
</head>
372
<body>
373
<div id="myplot"></div>
374
<script>
375
// Plot will be loaded here via AJAX
376
</script>
377
</body>
378
</html>
379
"""
380
```
381
382
### Flask Web Application Integration
383
384
```python
385
from flask import Flask, render_template, jsonify
386
from bokeh.plotting import figure
387
from bokeh.embed import components, json_item
388
from bokeh.resources import CDN
389
import numpy as np
390
391
app = Flask(__name__)
392
393
def create_plot():
394
"""Create a sample plot."""
395
p = figure(width=500, height=400)
396
x = np.random.random(50)
397
y = np.random.random(50)
398
p.circle(x, y, size=12, alpha=0.6)
399
return p
400
401
@app.route('/')
402
def index():
403
"""Main page with embedded plot."""
404
plot = create_plot()
405
script, div = components(plot)
406
407
return render_template('index.html',
408
script=script,
409
div=div,
410
css_resources=CDN.render_css(),
411
js_resources=CDN.render_js())
412
413
@app.route('/api/plot')
414
def plot_api():
415
"""API endpoint returning plot as JSON."""
416
plot = create_plot()
417
return jsonify(json_item(plot, "api-plot"))
418
419
# templates/index.html:
420
"""
421
<!DOCTYPE html>
422
<html>
423
<head>
424
<title>Flask + Bokeh</title>
425
{{ css_resources|safe }}
426
{{ js_resources|safe }}
427
</head>
428
<body>
429
<h1>My Flask Dashboard</h1>
430
{{ div|safe }}
431
{{ script|safe }}
432
433
<!-- AJAX plot container -->
434
<div id="api-plot"></div>
435
<button onclick="loadPlot()">Load Plot via API</button>
436
437
<script>
438
function loadPlot() {
439
fetch('/api/plot')
440
.then(response => response.json())
441
.then(item => {
442
Bokeh.embed.embed_item(item);
443
});
444
}
445
</script>
446
</body>
447
</html>
448
"""
449
450
if __name__ == '__main__':
451
app.run(debug=True)
452
```
453
454
### Django Integration
455
456
```python
457
# views.py
458
from django.shortcuts import render
459
from django.http import JsonResponse
460
from bokeh.plotting import figure
461
from bokeh.embed import components, json_item
462
from bokeh.resources import CDN
463
import numpy as np
464
465
def dashboard(request):
466
"""Django view with embedded Bokeh plot."""
467
# Create plot
468
p = figure(width=600, height=400, title="Django Dashboard")
469
x = np.linspace(0, 4*np.pi, 100)
470
p.line(x, np.sin(x), line_width=2, color='blue')
471
p.line(x, np.cos(x), line_width=2, color='red')
472
473
# Generate components
474
script, div = components(p)
475
476
context = {
477
'script': script,
478
'div': div,
479
'bokeh_css': CDN.render_css(),
480
'bokeh_js': CDN.render_js(),
481
}
482
483
return render(request, 'dashboard.html', context)
484
485
def plot_data(request):
486
"""API endpoint for dynamic plot data."""
487
# Generate new plot data
488
p = figure(width=400, height=300)
489
x = np.random.random(30)
490
y = np.random.random(30)
491
p.scatter(x, y, size=15, alpha=0.7)
492
493
return JsonResponse(json_item(p, "dynamic-plot"))
494
495
# templates/dashboard.html:
496
"""
497
<!DOCTYPE html>
498
<html>
499
<head>
500
<title>Django + Bokeh Dashboard</title>
501
{{ bokeh_css|safe }}
502
{{ bokeh_js|safe }}
503
</head>
504
<body>
505
<h1>Analytics Dashboard</h1>
506
507
<div class="main-plot">
508
{{ div|safe }}
509
</div>
510
511
<div id="dynamic-plot"></div>
512
<button onclick="updatePlot()">Update Data</button>
513
514
{{ script|safe }}
515
516
<script>
517
function updatePlot() {
518
fetch('{% url "plot_data" %}')
519
.then(response => response.json())
520
.then(item => {
521
Bokeh.embed.embed_item(item);
522
});
523
}
524
</script>
525
</body>
526
</html>
527
"""
528
```
529
530
### Server Application Embedding
531
532
```python
533
# server_embed.py - Bokeh server application
534
from bokeh.plotting import figure, curdoc
535
from bokeh.models import ColumnDataSource, Button, Column
536
import numpy as np
537
538
# Create interactive server application
539
source = ColumnDataSource(data=dict(x=[], y=[]))
540
541
p = figure(width=500, height=400, title="Server Application")
542
line = p.line('x', 'y', source=source, line_width=2)
543
544
button = Button(label="Update", button_type="success")
545
546
def update():
547
x = np.linspace(0, 4*np.pi, 100)
548
y = np.sin(x + np.random.random() * 2*np.pi)
549
source.data = dict(x=x, y=y)
550
551
button.on_click(update)
552
update() # Initial data
553
554
layout = Column(button, p)
555
curdoc().add_root(layout)
556
557
# External HTML page embedding the server app:
558
"""
559
<!DOCTYPE html>
560
<html>
561
<head>
562
<title>Embedded Server App</title>
563
</head>
564
<body>
565
<h1>My Website</h1>
566
<p>This is my regular website content.</p>
567
568
<!-- Embedded Bokeh server application -->
569
<div class="bokeh-app">
570
<script src="http://localhost:5006/server_embed/autoload.js" id="bokeh-server-app"></script>
571
</div>
572
573
<p>More website content below the app.</p>
574
</body>
575
</html>
576
"""
577
578
# Start server: bokeh serve server_embed.py --allow-websocket-origin=*
579
```
580
581
### Standalone HTML Generation
582
583
```python
584
from bokeh.plotting import figure
585
from bokeh.embed import file_html
586
from bokeh.resources import INLINE
587
from bokeh.layouts import column, row
588
import numpy as np
589
590
# Create multiple plots
591
p1 = figure(width=400, height=300, title="Sin Wave")
592
x = np.linspace(0, 4*np.pi, 100)
593
p1.line(x, np.sin(x), line_width=2)
594
595
p2 = figure(width=400, height=300, title="Scatter Plot")
596
x_scatter = np.random.random(50)
597
y_scatter = np.random.random(50)
598
p2.circle(x_scatter, y_scatter, size=10, alpha=0.6, color='red')
599
600
# Create layout
601
layout = column(
602
row(p1, p2),
603
sizing_mode='stretch_width'
604
)
605
606
# Generate complete HTML with inline resources
607
html = file_html(layout, INLINE, title="Standalone Dashboard")
608
609
# Save self-contained HTML file
610
with open("standalone_dashboard.html", "w") as f:
611
f.write(html)
612
613
print("Generated standalone HTML file with all resources embedded")
614
```