Dynamic panel apps embed inside Flask

Hello everyone,

I am refactoring my Panel application into a Flask WebApp (The app grew outside the scope of a single page webapp).

I was hoping to continue using Panel apps on different Routes. I have seen in the documentation how to do this: https://holoviews.org/user_guide/Deploying_Bokeh_Apps.html (Should this be inside the holoviews docs and not panel??)

  1. Run panel application (python panel_app.py)
  2. Pull session inside flask app with corresponding panel port

I have two questions:

  • Is it possible to parameterize the panel apps? (Say I have a bunch of datasets inside a db, and endpoints corresponding to the dataset /<int:id>/panel_app could I pull the data in automatically without using a “generic app” and choosing the dataset again?

  • I haven’t tried (yet) and maybe more a flask question but is there a way to start the panel app (maybe in a subprocess) when the endpoint is hit and kill it when left?

On a side note if it is useful for anyone I got dynamic holoviews working:

@app.route('/<int:_id>/map')
@login_required
def map(_id):
    ds = load_file(_id)
    lon, lat = get_lon_lat_names(_id)
    plot = ds.hvplot(x=lon, y=lat).opts(responsive=True)
    plot = hv.render(plot, backend='bokeh')
    html = file_html(plot, CDN)
    soup = BeautifulSoup(html, "html.parser")
    return render_template('app/map.html', head=soup.head, body=soup.body, data_file_id=_id)

Hi @WesleyTheGeolien

My take is that Panel is now at a stage where you don’t have to go to Flask or Django to support multipage apps.

You can just

panel serve app1.py app2.ipynb app3.py 

or inside your .py file

ROUTES = {"app1": app1_function, "app2": app2_function, "app3": app3_function}
panel.serve(ROUTES)

See https://panel.holoviz.org/user_guide/Deploy_and_Export.html for more info

And yes you can parametrize your app. There is a reference notebook here https://panel.holoviz.org/gallery/simple/sync_location.html#simple-gallery-sync-location. (Please download and run the notebook for it to work).

I also want to create a larger site of Panel apps for awesome-panel.org and for work. I’ve created a template you can use in practice or for inspiration.

Checkout this video introduction https://www.youtube.com/embed/QmwSyQqkKvI

2 Likes

Interesting I wasn’t aware of the syncing in locations could be useful! From what I understand though it only works with query parameters?

As for launching multiple apps I was somewhat aware of this but I thought the best UX in my case would be to have things carry over from routes or other rather than having separate applications, I am sure I could get it working with panel it just felt more “elegant” to do it with flask. It could just be though that I am not familiar enough with the panel ecosystem though

2 Likes

So I think I got something roughly working to how I want it using flask + panel.

It doesn’t dynamically load / serve a panel app.

  1. Start the panel app (python -m panel serve sync.py --allow-websocket-origin=localhost:5000 where flask is running on port 5000
  2. Inside my flask app I have
from bokeh.embed import server_document
from flask import render_template

@app.route('/<int:_id>/internal_oceans')
def internal_oceans(_id):
    script = server_document(url='http://localhost:5006/sync', 
        arguments={'slider_value':67}) 
    return render_template("app/internal_oceans.html", script=script)

The arguments are passed to the Bokeh Document which is accessible through panel.state.curdoc so stringing that all together we have access to arguments via panel.state.curdoc.session_context.request.arguments

3 Likes