Send data from host server (django or flask) to bokeh session

Hello,

I was looking at the Running a Bokeh server, and I am trying to make sure I understand how the app_hooks.py and request_handler.py work for interfacing with a django project.

What I am trying to do is be able to pass variables or information to a bokeh session instance and have that session plot information based on the variables passed. For example, a database query where the username is passed to limit data access based on the api to get data that the bokeh app uses to get and plot data.

My understanding is you can use arguments in pull_session as a dictionary of string keys and string values. Then in the app you can call curdoc().context_session.requests.arguments as in Accessing HTTP requests?

# Django
def myview(request):
    url = "http://localhost:5006/bokeh_app"
    with pull_session(url=url, argumnets={'username' : username}) as session:
        # NOTE is this possible? Or another method of accessing these in bokeh
        # session['username'] = username
        script = server_session(session_id=session.id, url=url)
        return render(request, 'mytemplate.html', {'script' : script})
# bokeh_app/main.py
...
username = None
...
args = curdoc().session_context.requests.arguments
username = args.get('username')[0]
# Do stuff with username
...

Is this seem right? And/or is it possible to access session variables like I have in the comment in the Django section?

Is it possible to handle setting of variables for the main script for a session from app_hooks.py? My understanding is the documentation implies this, if calling the function on_session_created. If so how does one supress the default settings of variables in the main.py.

If not then what would be an example use case of on_session_created? Can it even handle passing variables or modifying the state of a session before executing, or is it used for other internal setups?

Thanks again for the help and clarification!

My understanding is you can use arguments in pull_session as a dictionary of string keys and string values. Then in the app you can call curdoc().context_session.requests.arguments as in Accessing HTTP requests?

Yes but be aware that those are HTTP arguments and so they are appended directly to the URL, which might show up in logs for proxies, load-balancers, or other intervening network systems. The curdoc().session_context.request object can also access request headers or cookies, in case those are more applicable.

If this is regarding auth concerns (as it seems to be?) then you might have look a the the Panel repo. Panel is built on top of Bokeh and they have implemented more substantial auth-hooks (e.g. for OAuth): https://github.com/holoviz/panel/blob/master/panel/auth.py In particular, an auth handler could set cookies or headers that can be accessed on the session_context.

I don’t think so, at least if you mean Python vars in the app script. on_session_created gets passed a SessionContext, which has the new Session. The Session has the Document for the session, which in turn is available as curdoc() in the app code. So you could potentially attach information the Document that would show up on curdoc() in the app code.

But I should be clear: I’ve never actually tried this specifically, or seen anyone report trying it. There are full unit tests to ensure that on_session_created is called when it is supposed to, with the argument it is supposed to called with. But there is very little (if any) “real-world” experience of anyone using this feature that I know of.

1 Like

Oh interesting, I noticed their integration with django is still set to v2.*, they seem to be stuck on relying on the bokeh.server.django. Does that mean it is linked to using the older version of bokeh before the breakage with django v3, and v4?

In my case I would have the apps running behind a reverse proxy within the same network, with only the django app being accessible from the outside on the server. So I am unsure if I need the OAuth ability, but I was curious about Oauth with Django. I see you can use the predefined Authorization Providers with Panel, but do you know if they allow one to provide their own Authorization server? I didn’t see that in the documentation when scanning it.

This may be fine, if I can create session variables in django, and have defaults set on the bokeh app that could be sufficient or something to play with. One question pops to mind, when I pull_session it spawns an instance of a document. If the defaults are set on session creation and I create a session context variable after pull_session, the document was already processed, no? So I would need some way to post document session creation to load/update variables. Is there any tooling to check for an update to session_context? Such as an event_handler? Or block processing until you get an update to resume?

Hence why I am curious why app_hooks.py. Would it be (or is it) possible to be able to pass session_context variables on a call of pull_session? Or is this what arguments is used for?

I can play with it and see if it works (or breaks)

PS. Thanks so much for spending time answering questions, I really appreciate it!

We should back up slightly. The original question seemed to regard server_session, server_document, etc. which work with any web framework (Django, Flask, whatever) with a separate Bokeh server process(es). The bokeh.server.django API was some experimental work to afford a “direct integration” with Django, allowing the Bokeh app to run directly inside Django with no separate Bokeh server process. However, that work has been largely abandoned (no one in core team to maintain it) and I would actually expect it to be removed in time. [1] I would advise against using bokeh.server.django at this point.

In my case I would have the apps running behind a reverse proxy within the same network, with only the django app being accessible from the outside on the server.

Just to be clear, the Bokeh server must be able to make a websocket connection with the viewer’s browser. You can enforce that embeds only work on origins you specify, you can enable requirements for signed session ids, and you can layer on integrations with auth (e.g. OAuth). But the Bokeh server has to be reachable in some way or other.

I see you can use the predefined Authorization Providers with Panel, but do you know if they allow one to provide their own Authorization server? I didn’t see that in the documentation when scanning it.

I don’t know the answer to that. cc @Philipp_Rudiger or @James_A_Bednar1 may be able to comment.

If the defaults are set on session creation and I create a session context variable after pull_session , the document was already processed, no?

You can customize the document that is in the retrieved session (that’s the intent of pull_session, in fact), see this example:

https://github.com/bokeh/bokeh/blob/branch-3.0/examples/embed/server_session

Hence why I am curious why app_hooks.py . Would it be (or is it) possible to be able to pass session_context variables on a call of pull_session?

I’m not sure I understand the question, some pseudocode might help

Or is this what arguments is used for?

Arguments is purely for supplying optional HTTP ?foo=bar args to the URL that hits the Bokeh server.


  1. What I would really like is for the Bokeh protocol to be “liberated” from Tornado and become agnostic wrt transport so that it could generically be embedded into web frameworks without the special casing that was bokeh.server.django. That’s a big lift though, I am not sure when or if it will happen. ↩︎

Yes, the original question is as you expected. I just noticed in the Panel documentation, when they mention integrating with Django, that they require to pull down django-2.*, which used the old (effectively defunct), bokeh.server.django. I am trying to focus on using bokeh as intended in the latest release. Or find a suitable tool that allows for the placement or features required to get around the hurdles. If Bokeh v3.0 has them (if you suspect may be incorporated) I may be able to wait until then or could possibly help out. As we are looking to have this functionality in an Django framework with users and segregating queries based on login information. I understand code is ready when it is, so I won’t ask what the time frames are.

The rapid deployment of the bokeh server is handy as there could be a lot of apps being made, if this works well, but on the team I would be likely doing any “heavy” development; hence why I am asking so many questions to expediate my development time.

Just to be clear, the Bokeh server must be able to make a websocket connection with the viewer’s browser. You can enforce that embeds only work on origins you specify, you can enable requirements for signed session ids, and you can layer on integrations with auth (e.g. OAuth). But the Bokeh server has to be reachable in some way or other.

If I understand this correctly, you mean even though the django server is an allowed websocket connection (eg. --allow-websocket-orign="django.example.com"), the Bokeh server still needs to be able to access the users IP (not in the local network for example) of their browser? My intent is for the server_session to be served via a template from django to a users browser. Would I need to then pass --allow-websocket-orign="*" to bokeh serve? Or being accessible via the browser through djangos template will work with --allow-websocket-origin="django.example.com"

You can customize the document that is in the retrieved session (that’s the intent of pull_session, in fact), see this example:

bokeh/examples/embed/server_session at branch-3.0 · bokeh/bokeh · GitHub

Okay I will play with this to ensure I understand this correctly.

I’m not sure I understand the question, some pseudocode might help

I think I am just hung up on the language of the documentation, such that you should be able to pass session context data to on_session_create and have some changes to the document, or an event that can be triggered in the main.py code. An example would be,

# app_hooks.py
def on_session_create(session_context):
    if 'myvar' in session_context.keys():
        # set myvar in main.py
        main_script.myvar = session_context['myvar']

Or maybe some function that detects session specific contexts in the main.py

from bokeh.client import session_new_context_helper #NOT REAL
from bokeh.plotting import curdoc
...

default_value = 5
myvar = session_new_context_helper(curdoc, "myvar", default_value)

...

I am getting hung up thinking about when you call pull_session, that the document gets generated first, and any context you create before calling server_session isn’t able to be processed unless you do some event handling. So I am worried the document generates data first and shows it, then updates to the new data when the contexts are handled. I may be over thinking it though.

  1. What I would really like is for the Bokeh protocol to be “liberated” from Tornado and become agnostic wrt transport so that it could generically be embedded into web frameworks without the special casing that was bokeh.server.django. That’s a big lift though, I am not sure when or if it will happen
    [/quote]

That would be cool! But I imagine a huge daunting task. I am unsure of any tool that has the features I would like to see (in general from my posts), and it would be cool to have bokeh have it to make it more desirable in more dynamic setups.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.