CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-bokeh

Interactive plots and applications in the browser from Python

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

embedding-integration.mddocs/

Embedding and Integration

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.

Capabilities

HTML Component Generation

Functions for generating HTML and JavaScript components that can be embedded in web pages.

def components(plot_objects, wrap_script=True, wrap_plot_info=True):
    """
    Generate HTML components for embedding plots.
    
    Returns separate script and div elements that can be embedded
    in existing HTML pages. This is the most flexible embedding method.
    
    Parameters:
    - plot_objects: Single plot/layout or sequence of plot objects
    - wrap_script: Whether to wrap JavaScript in <script> tags
    - wrap_plot_info: Whether to wrap plot info in JSON
    
    Returns:
    Tuple[str, Union[str, List[str]]]: (script, div_elements)
    - script: JavaScript code to render the plots
    - div_elements: HTML div element(s) as placeholder(s)
    
    For single plot: returns (script, div_string)
    For multiple plots: returns (script, [div1, div2, ...])
    """

def file_html(models, resources, title=None, template=None, template_variables=None):
    """
    Generate complete standalone HTML file content.
    
    Creates a full HTML document containing plots with all necessary
    resources. Ideal for saving self-contained HTML files.
    
    Parameters:
    - models: Plot objects or layouts to include
    - resources: Resources object specifying how to include BokehJS
    - title: HTML document title
    - template: Custom Jinja2 template (optional)
    - template_variables: Variables for template rendering
    
    Returns:
    str: Complete HTML document as string
    """

JSON Serialization

Functions for generating JSON representations of plots for custom embedding scenarios.

def json_item(model, target=None):
    """
    Generate JSON representation for embedding.
    
    Creates a JSON object containing all plot data and configuration
    that can be rendered by BokehJS. Useful for AJAX-based applications
    and custom integration scenarios.
    
    Parameters:
    - model: Plot object or layout to serialize
    - target: Target element ID for rendering (optional)
    
    Returns:
    str: JSON string containing plot specification
    
    The JSON can be used with bokehjs.embed.embed_item() in JavaScript.
    """

Dynamic Loading

Functions for dynamic plot loading and autoloading scenarios.

def autoload_static(model, resources, script_path):
    """
    Generate script for static autoloading.
    
    Creates JavaScript that can be included via <script> tag to
    automatically load and render a plot. The plot data is embedded
    in the script itself.
    
    Parameters:
    - model: Plot object or layout to embed
    - resources: Resources object for BokehJS inclusion
    - script_path: Path where the script will be served
    
    Returns:
    str: JavaScript code for autoloading the plot
    
    Usage: Save returned script to a .js file and include via:
    <script src="path/to/generated/script.js"></script>
    """

def autoload_server(model, app_path, server_id=None, 
                   server_url="http://localhost:5006", **kwargs):
    """
    Generate script for server-based autoloading.
    
    Creates JavaScript that loads plots from a running Bokeh server.
    Enables embedding of server applications in external websites.
    
    Parameters:
    - model: Plot object or layout (unused, kept for compatibility)
    - app_path: Path to server application
    - server_id: Server session ID (optional)
    - server_url: URL of Bokeh server
    
    Returns:
    str: JavaScript code for loading from server
    """

Server Document Embedding

Functions for embedding server-based applications.

def server_document(url, relative_urls=False, resources=None, **kwargs):
    """
    Embed server document in existing page.
    
    Generates HTML/JavaScript to embed a live server application
    document in an existing webpage with bidirectional communication.
    
    Parameters:
    - url: URL to server application
    - relative_urls: Whether to use relative URLs
    - resources: Resources object (optional)
    
    Returns:
    str: HTML/JavaScript for embedding server document
    """

def server_session(model_or_server_id, session_id=None, url=None):
    """
    Embed specific server session.
    
    Embeds a specific server session, allowing multiple sessions
    of the same application to be embedded independently.
    
    Parameters:
    - model_or_server_id: Model object or server session ID
    - session_id: Specific session ID to embed
    - url: Server URL
    
    Returns:
    str: HTML/JavaScript for embedding server session
    """

Resources Management

Classes for controlling how BokehJS resources are included in embedded content.

class Resources:
    """
    Controls how BokehJS resources are included.
    
    Manages the inclusion of BokehJS JavaScript and CSS files
    in generated HTML. Supports various deployment scenarios.
    """
    def __init__(self, mode='inline', version=None, root_dir=None,
                 minified=True, log_level='info', root_url=None,
                 path_versioner=None):
        """
        Parameters:
        - mode: Resource inclusion mode
                'inline' - Include resources directly in HTML
                'cdn' - Link to CDN-hosted resources  
                'server' - Link to local server resources
                'server-dev' - Link to development server resources
        - version: Specific Bokeh version for CDN mode
        - root_dir: Root directory for relative paths
        - minified: Use minified JavaScript files
        - log_level: JavaScript logging level ('trace', 'debug', 'info', 'warn', 'error', 'fatal')
        - root_url: Base URL for server mode
        - path_versioner: Function to add version info to paths
        """
    
    mode: str
    version: Optional[str]
    minified: bool
    
    # Resource URL generation
    def js_files(self):
        """Get list of JavaScript file URLs."""
    
    def css_files(self):
        """Get list of CSS file URLs."""
    
    def js_raw(self):
        """Get raw JavaScript content (inline mode only)."""
    
    def css_raw(self):
        """Get raw CSS content (inline mode only)."""

# Pre-configured resource instances
CDN: Resources        # CDN-hosted resources (default)
INLINE: Resources     # Inline resources (self-contained)

Render Root

Class for advanced embedding scenarios with custom rendering containers.

class RenderRoot:
    """
    Root rendering container for embedding.
    
    Provides fine-grained control over how plots are rendered
    and embedded in custom containers.
    """
    def __init__(self, elementid, child):
        """
        Parameters:
        - elementid: HTML element ID for rendering target
        - child: Plot object or layout to render
        """
    
    elementid: str
    child: Model

Usage Examples

Basic HTML Embedding

from bokeh.plotting import figure
from bokeh.embed import components
from bokeh.resources import CDN
import numpy as np

# Create plot
p = figure(width=400, height=400, title="Embedded Plot")
x = np.linspace(0, 4*np.pi, 100)
p.line(x, np.sin(x), line_width=2)

# Generate components
script, div = components(p)

# Create HTML page
html_template = f"""
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>My Dashboard</title>
    {CDN.render_css()}
    {CDN.render_js()}
</head>
<body>
    <h1>My Custom Dashboard</h1>
    <div class="plot-container">
        {div}
    </div>
    <p>This plot is embedded in custom HTML.</p>
    {script}
</body>
</html>
"""

# Save HTML file
with open("embedded_plot.html", "w") as f:
    f.write(html_template)

Multiple Plots Embedding

from bokeh.plotting import figure
from bokeh.embed import components
from bokeh.resources import CDN
import numpy as np

# Create multiple plots
plots = []
functions = [np.sin, np.cos, np.tan]
colors = ['blue', 'red', 'green']

for i, (func, color) in enumerate(zip(functions, colors)):
    p = figure(width=300, height=300, title=f"Plot {i+1}")
    x = np.linspace(0, 4*np.pi, 100)
    y = func(x)
    if func == np.tan:
        y = np.clip(y, -5, 5)  # Limit tan values
    p.line(x, y, color=color, line_width=2)
    plots.append(p)

# Generate components for all plots
script, divs = components(plots)

# Create HTML with multiple plots
html = f"""
<!DOCTYPE html>
<html>
<head>
    <title>Multiple Plots</title>
    {CDN.render_css()}
    {CDN.render_js()}
    <style>
        .plot-grid {{
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 20px;
            padding: 20px;
        }}
    </style>
</head>
<body>
    <h1>Function Comparison</h1>
    <div class="plot-grid">
        {divs[0]}
        {divs[1]}
        {divs[2]}
    </div>
    {script}
</body>
</html>
"""

with open("multiple_plots.html", "w") as f:
    f.write(html)

JSON Embedding for AJAX

from bokeh.plotting import figure
from bokeh.embed import json_item
import json
import numpy as np

# Create plot
p = figure(width=500, height=400, title="AJAX Plot")
x = np.random.random(100)
y = np.random.random(100)
p.circle(x, y, size=10, alpha=0.6)

# Generate JSON
plot_json = json_item(p, "myplot")

# JavaScript for AJAX loading
js_code = f"""
// JavaScript code for embedding via AJAX
fetch('/api/plot-data')
    .then(response => response.json())
    .then(item => {{
        Bokeh.embed.embed_item(item);
    }});

// Or directly embed the JSON item:
const plotItem = {plot_json};
Bokeh.embed.embed_item(plotItem);
"""

# HTML template for AJAX embedding
html = """
<!DOCTYPE html>
<html>
<head>
    <script src="https://cdn.bokeh.org/bokeh/release/bokeh-3.0.0.min.js"></script>
</head>
<body>
    <div id="myplot"></div>
    <script>
        // Plot will be loaded here via AJAX
    </script>
</body>
</html>
"""

Flask Web Application Integration

from flask import Flask, render_template, jsonify
from bokeh.plotting import figure
from bokeh.embed import components, json_item
from bokeh.resources import CDN
import numpy as np

app = Flask(__name__)

def create_plot():
    """Create a sample plot."""
    p = figure(width=500, height=400)
    x = np.random.random(50)
    y = np.random.random(50)
    p.circle(x, y, size=12, alpha=0.6)
    return p

@app.route('/')
def index():
    """Main page with embedded plot."""
    plot = create_plot()
    script, div = components(plot)
    
    return render_template('index.html', 
                         script=script, 
                         div=div,
                         css_resources=CDN.render_css(),
                         js_resources=CDN.render_js())

@app.route('/api/plot')
def plot_api():
    """API endpoint returning plot as JSON."""
    plot = create_plot()
    return jsonify(json_item(plot, "api-plot"))

# templates/index.html:
"""
<!DOCTYPE html>
<html>
<head>
    <title>Flask + Bokeh</title>
    {{ css_resources|safe }}
    {{ js_resources|safe }}
</head>
<body>
    <h1>My Flask Dashboard</h1>
    {{ div|safe }}
    {{ script|safe }}
    
    <!-- AJAX plot container -->
    <div id="api-plot"></div>
    <button onclick="loadPlot()">Load Plot via API</button>
    
    <script>
    function loadPlot() {
        fetch('/api/plot')
            .then(response => response.json())
            .then(item => {
                Bokeh.embed.embed_item(item);
            });
    }
    </script>
</body>
</html>
"""

if __name__ == '__main__':
    app.run(debug=True)

Django Integration

# views.py
from django.shortcuts import render
from django.http import JsonResponse
from bokeh.plotting import figure
from bokeh.embed import components, json_item
from bokeh.resources import CDN
import numpy as np

def dashboard(request):
    """Django view with embedded Bokeh plot."""
    # Create plot
    p = figure(width=600, height=400, title="Django Dashboard")
    x = np.linspace(0, 4*np.pi, 100)
    p.line(x, np.sin(x), line_width=2, color='blue')
    p.line(x, np.cos(x), line_width=2, color='red')
    
    # Generate components
    script, div = components(p)
    
    context = {
        'script': script,
        'div': div,
        'bokeh_css': CDN.render_css(),
        'bokeh_js': CDN.render_js(),
    }
    
    return render(request, 'dashboard.html', context)

def plot_data(request):
    """API endpoint for dynamic plot data."""
    # Generate new plot data
    p = figure(width=400, height=300)
    x = np.random.random(30)
    y = np.random.random(30)
    p.scatter(x, y, size=15, alpha=0.7)
    
    return JsonResponse(json_item(p, "dynamic-plot"))

# templates/dashboard.html:
"""
<!DOCTYPE html>
<html>
<head>
    <title>Django + Bokeh Dashboard</title>
    {{ bokeh_css|safe }}
    {{ bokeh_js|safe }}
</head>
<body>
    <h1>Analytics Dashboard</h1>
    
    <div class="main-plot">
        {{ div|safe }}
    </div>
    
    <div id="dynamic-plot"></div>
    <button onclick="updatePlot()">Update Data</button>
    
    {{ script|safe }}
    
    <script>
    function updatePlot() {
        fetch('{% url "plot_data" %}')
            .then(response => response.json())
            .then(item => {
                Bokeh.embed.embed_item(item);
            });
    }
    </script>
</body>
</html>
"""

Server Application Embedding

# server_embed.py - Bokeh server application
from bokeh.plotting import figure, curdoc
from bokeh.models import ColumnDataSource, Button, Column
import numpy as np

# Create interactive server application
source = ColumnDataSource(data=dict(x=[], y=[]))

p = figure(width=500, height=400, title="Server Application")
line = p.line('x', 'y', source=source, line_width=2)

button = Button(label="Update", button_type="success")

def update():
    x = np.linspace(0, 4*np.pi, 100)
    y = np.sin(x + np.random.random() * 2*np.pi)
    source.data = dict(x=x, y=y)

button.on_click(update)
update()  # Initial data

layout = Column(button, p)
curdoc().add_root(layout)

# External HTML page embedding the server app:
"""
<!DOCTYPE html>
<html>
<head>
    <title>Embedded Server App</title>
</head>
<body>
    <h1>My Website</h1>
    <p>This is my regular website content.</p>
    
    <!-- Embedded Bokeh server application -->
    <div class="bokeh-app">
        <script src="http://localhost:5006/server_embed/autoload.js" id="bokeh-server-app"></script>
    </div>
    
    <p>More website content below the app.</p>
</body>
</html>
"""

# Start server: bokeh serve server_embed.py --allow-websocket-origin=*

Standalone HTML Generation

from bokeh.plotting import figure
from bokeh.embed import file_html
from bokeh.resources import INLINE
from bokeh.layouts import column, row
import numpy as np

# Create multiple plots
p1 = figure(width=400, height=300, title="Sin Wave")
x = np.linspace(0, 4*np.pi, 100)
p1.line(x, np.sin(x), line_width=2)

p2 = figure(width=400, height=300, title="Scatter Plot")  
x_scatter = np.random.random(50)
y_scatter = np.random.random(50)
p2.circle(x_scatter, y_scatter, size=10, alpha=0.6, color='red')

# Create layout
layout = column(
    row(p1, p2),
    sizing_mode='stretch_width'
)

# Generate complete HTML with inline resources
html = file_html(layout, INLINE, title="Standalone Dashboard")

# Save self-contained HTML file
with open("standalone_dashboard.html", "w") as f:
    f.write(html)

print("Generated standalone HTML file with all resources embedded")

Install with Tessl CLI

npx tessl i tessl/pypi-bokeh

docs

client-server.md

colors-transforms.md

command-line.md

document-management.md

embedding-integration.md

events-interactivity.md

index.md

io-operations.md

layouts.md

models-data-sources.md

plotting-interface.md

server-applications.md

widgets.md

tile.json