1

Ultimately, I'm trying to serve interactive bokeh plots on a website. I'm using Ubuntu 18.04

nginx/1.14.0, Django==2.1, gunicorn==19.9.0, Python 3.6.5, bokeh-0.13.0

I am successful at seeing the bokeh plot locally and I was successful without django by using directives in nginx's website.conf ...

location /bkapp {     
    proxy_pass http://127.0.0.1:5100;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host:$server_port;
    proxy_buffering off;
}

and :

bokeh serve bkapp.py --port 5100 --prefix=bkapp --allow-websocket-origin=www.website.com

...to communicate with the bokeh server at www.website.com/bkapp in my browser (not locally). I did not have to add any port triggers or virtual servers for port 5100 on my router.

!!!!!!!!!!!!!!!!!!!!

HOWEVER, I WOULD LIKE TO ROUTE THROUGH django/gunicorn: currently I'm receiving Server Error (500)

!!!!!!!!!!!!!!!!!!!!

I think my problem is routing/communication once the request enter's the views.py. I think my problem is here and I've been tweaking the code from Embed an interactive Bokeh in django views .

views.py is properly configured to respond to typical requests but can't connect/work with the local bokeh server

For serving it to the internet, I'm using the command:

bokeh serve perceptron.py --port 5100 --prefix=perceptron --allow-websocket-origin=localhost:5100

views.py:

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
session = pull_session(url="http://localhost:5100/")
script = autoload_server(model=None,
                         app_path="/bkapp",
                         url="http://localhost:5100/",
                         session_id = session.id)

return render(request, 'bkapp/index.html', {
    'script': script})

bkapp/index.html:

{% extends 'home/base.html' %}
{% block content %}

<div >

<link href="https://cdn.bokeh.org/bokeh/release/bokeh-0.13.0.min.css" rel="stylesheet" type="text/css">
<link href="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-0.13.0.min.css" rel="stylesheet" type="text/css">
<link href="https://cdn.bokeh.org/bokeh/release/bokeh-tables-0.13.0.min.css" rel="stylesheet" type="text/css">
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-0.13.0.min.js"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-0.13.0.min.js"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-0.13.0.min.js"></script>
{{ script | safe }}

</div>

{% endblock %}

nginx's website.conf:

upstream website_server {
    server unix:/home/jeff/dev/run/gunicorn.sock fail_timeout=0;
}

server {
    listen 80;
    server_name website.com www.website.com;
    return 301 https://$server_name$request_uri;
}


server {

    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name website.com www.website.com;

    add_header Strict-Transport-Security "max-age=31536000";

    ssl_certificate /etc/letsencrypt/live/website.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/website.com/privkey.pem;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers 'XXX';


    root /usr/share/nginx/html;
    index index.html index.htm;

    location /static/ {
        alias   /home/jeff/website/static/;
    }

    location /media/ {
        expires -1;
        alias /home/jeff/website/media/;
        add_header Cache-Control "public";
    }


    client_max_body_size 4G;
    access_log /home/jeff/website/logs/nginx-access.log;
    error_log /home/jeff/website/logs/nginx-error.log;



    location / {
        proxy_pass http://127.0.0.1:5100;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        #proxy_set_header Host $http_host;
        proxy_set_header Host $host:$server_port;
        proxy_buffering off;
        proxy_redirect off;
        if (!-f $request_filename) {
            proxy_pass http://website_server;
            break;
        }
    }



    error_page 500 502 503 504 /500.html;
    location = /500.html {
        root /home/jeff/website/static/;
    }
}

and here's a bkapp.py you can imitate (copied from bokeh's tutorials):

from random import random

from bokeh.layouts import column
from bokeh.models import Button
from bokeh.palettes import RdYlBu3
from bokeh.plotting import figure, curdoc

# create a plot and style its properties
p = figure(x_range=(0, 100), y_range=(0, 100), toolbar_location=None)
p.border_fill_color = 'black'
p.background_fill_color = 'black'
p.outline_line_color = None
p.grid.grid_line_color = None

# add a text renderer to our plot (no data yet)
r = p.text(x=[], y=[], text=[], text_color=[], text_font_size="20pt",
       text_baseline="middle", text_align="center")

i = 0

ds = r.data_source

# create a callback that will add a number in a random location
def callback():
    global i

    # BEST PRACTICE --- update .data in one step with a new dict
    new_data = dict()
    new_data['x'] = ds.data['x'] + [random()*70 + 15]
    new_data['y'] = ds.data['y'] + [random()*70 + 15]
    new_data['text_color'] = ds.data['text_color'] + [RdYlBu3[i%3]]
    new_data['text'] = ds.data['text'] + [str(i)]
    ds.data = new_data

    i = i + 1

# add a button widget and configure with the call back
button = Button(label="Press Me")
button.on_click(callback)

# put the button and plot in a layout and add to the document
curdoc().add_root(column(button, p))

UPDATE Tuesday, Sept 4th, 2018 0955 AM PDT: Added session = pull_session() and session id to script in views.py, now each call to website/bkapp causes: bokeh server error:

 404 GET /ws?bokeh-protocol-version=1.0&bokeh-session-id=wBvizF5w1yUuFqsa55Ikm3zngMSpcauhG3IvtoICU4Sb (127.0.0.1) 1.66ms

gunicorn error:

File "/home/jeff/dev/lib/python3.6/site-packages/bokeh/client/session.py", line 343, in pull
raise IOError("Cannot pull session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)")
OSError: Cannot pull session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)
bigreddot
  • 33,642
  • 5
  • 69
  • 122
Kevin Preston
  • 553
  • 1
  • 4
  • 14
  • does this help? https://github.com/konoanalytics/BokehDjango – Jonathan Feb 12 '19 at 05:47
  • Thanks for the link. I'm currently not working on this, I bypassed Django and the Bokeh plot is served independent of Django. If I get the motivation, I'll return to scrutinize the code in the above link and maybe find the code snippets where Django and Bokeh connect. – Kevin Preston Feb 12 '19 at 23:16

0 Answers0