Skip to content

Commit

Permalink
Added FastApi in the user guide for embedding apps (#2870)
Browse files Browse the repository at this point in the history
  • Loading branch information
t-houssian authored and philippjfr committed Nov 4, 2021
1 parent 3250388 commit 1351e7f
Show file tree
Hide file tree
Showing 13 changed files with 690 additions and 1 deletion.
40 changes: 40 additions & 0 deletions examples/apps/fastApi/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from bokeh.embed import server_document
from panel.io.server import Server
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from starlette.middleware.cors import CORSMiddleware
from starlette.middleware import Middleware
from threading import Thread
from tornado.ioloop import IOLoop

from sliders.pn_app import createApp

app = FastAPI()
templates = Jinja2Templates(directory="templates")

app.add_middleware( # Middleware to serve panel apps asynchronously via starlette
CORSMiddleware,
allow_origins=['*'],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)


@app.get("/")
async def bkapp_page(request: Request):
script = server_document('http://127.0.0.1:5000/app')
return templates.TemplateResponse("base.html", {"request": request, "script": script})


def bk_worker():
server = Server({'/app': createApp},
port=5000, io_loop=IOLoop(),
allow_websocket_origin=["*"])

server.start()
server.io_loop.start()

th = Thread(target=bk_worker)
th.daemon = True
th.start()
8 changes: 8 additions & 0 deletions examples/apps/fastApi/sliders/pn_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import panel as pn

from .sinewave import SineWave

def createApp(doc):
sw = SineWave()
row = pn.Row(sw.param, sw.plot)
row.server_doc(doc)
35 changes: 35 additions & 0 deletions examples/apps/fastApi/sliders/sinewave.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import numpy as np
import param
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure


class SineWave(param.Parameterized):
offset = param.Number(default=0.0, bounds=(-5.0, 5.0))
amplitude = param.Number(default=1.0, bounds=(-5.0, 5.0))
phase = param.Number(default=0.0, bounds=(0.0, 2 * np.pi))
frequency = param.Number(default=1.0, bounds=(0.1, 5.1))
N = param.Integer(default=200, bounds=(0, None))
x_range = param.Range(default=(0, 4 * np.pi), bounds=(0, 4 * np.pi))
y_range = param.Range(default=(-2.5, 2.5), bounds=(-10, 10))

def __init__(self, **params):
super(SineWave, self).__init__(**params)
x, y = self.sine()
self.cds = ColumnDataSource(data=dict(x=x, y=y))
self.plot = figure(plot_height=400, plot_width=400,
tools="crosshair, pan, reset, save, wheel_zoom",
x_range=self.x_range, y_range=self.y_range)
self.plot.line('x', 'y', source=self.cds, line_width=3, line_alpha=0.6)

@param.depends('N', 'frequency', 'amplitude', 'offset', 'phase', 'x_range', 'y_range', watch=True)
def update_plot(self):
x, y = self.sine()
self.cds.data = dict(x=x, y=y)
self.plot.x_range.start, self.plot.x_range.end = self.x_range
self.plot.y_range.start, self.plot.y_range.end = self.y_range

def sine(self):
x = np.linspace(0, 4 * np.pi, self.N)
y = self.amplitude * np.sin(self.frequency * x + self.phase) + self.offset
return x, y
9 changes: 9 additions & 0 deletions examples/apps/fastApi/templates/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>Panel in FastAPI: sliders</title>
</head>
<body>
{{ script|safe }}
</body>
</html>
45 changes: 45 additions & 0 deletions examples/apps/fastApi_multi_apps/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from bokeh.embed import server_document
from panel.io.server import Server
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from starlette.middleware.cors import CORSMiddleware
from starlette.middleware import Middleware
from threading import Thread
from tornado.ioloop import IOLoop

from sliders.pn_app import createApp
from sliders2.pn_app import createApp2

app = FastAPI()
templates = Jinja2Templates(directory="templates")

app.add_middleware( # Middleware to serve panel apps asynchronously via starlette
CORSMiddleware,
allow_origins=['*'],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)


@app.get("/")
async def bkapp_page(request: Request):
script = server_document('http://127.0.0.1:5000/app')
return templates.TemplateResponse("base.html", {"request": request, "script": script})

@app.get("/app2")
async def bkapp_page2(request: Request):
script = server_document('http://127.0.0.1:5000/app2')
return templates.TemplateResponse("app2.html", {"request": request, "script": script})

def bk_worker():
server = Server({'/app': createApp, '/app2': createApp2},
port=5000, io_loop=IOLoop(),
allow_websocket_origin=["*"])

server.start()
server.io_loop.start()

th = Thread(target=bk_worker)
th.daemon = True
th.start()
8 changes: 8 additions & 0 deletions examples/apps/fastApi_multi_apps/sliders/pn_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import panel as pn

from .sinewave import SineWave

def createApp(doc):
sw = SineWave()
row = pn.Row(sw.param, sw.plot)
row.server_doc(doc)
35 changes: 35 additions & 0 deletions examples/apps/fastApi_multi_apps/sliders/sinewave.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import numpy as np
import param
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure


class SineWave(param.Parameterized):
offset = param.Number(default=0.0, bounds=(-5.0, 5.0))
amplitude = param.Number(default=1.0, bounds=(-5.0, 5.0))
phase = param.Number(default=0.0, bounds=(0.0, 2 * np.pi))
frequency = param.Number(default=1.0, bounds=(0.1, 5.1))
N = param.Integer(default=200, bounds=(0, None))
x_range = param.Range(default=(0, 4 * np.pi), bounds=(0, 4 * np.pi))
y_range = param.Range(default=(-2.5, 2.5), bounds=(-10, 10))

def __init__(self, **params):
super(SineWave, self).__init__(**params)
x, y = self.sine()
self.cds = ColumnDataSource(data=dict(x=x, y=y))
self.plot = figure(plot_height=400, plot_width=400,
tools="crosshair, pan, reset, save, wheel_zoom",
x_range=self.x_range, y_range=self.y_range)
self.plot.line('x', 'y', source=self.cds, line_width=3, line_alpha=0.6)

@param.depends('N', 'frequency', 'amplitude', 'offset', 'phase', 'x_range', 'y_range', watch=True)
def update_plot(self):
x, y = self.sine()
self.cds.data = dict(x=x, y=y)
self.plot.x_range.start, self.plot.x_range.end = self.x_range
self.plot.y_range.start, self.plot.y_range.end = self.y_range

def sine(self):
x = np.linspace(0, 4 * np.pi, self.N)
y = self.amplitude * np.sin(self.frequency * x + self.phase) + self.offset
return x, y
8 changes: 8 additions & 0 deletions examples/apps/fastApi_multi_apps/sliders2/pn_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import panel as pn

from .sinewave import SineWave

def createApp2(doc):
sw = SineWave()
row = pn.Row(sw.param, sw.plot)
row.server_doc(doc)
35 changes: 35 additions & 0 deletions examples/apps/fastApi_multi_apps/sliders2/sinewave.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import numpy as np
import param
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure


class SineWave(param.Parameterized):
offset = param.Number(default=0.0, bounds=(-5.0, 5.0))
amplitude = param.Number(default=1.0, bounds=(-5.0, 5.0))
phase = param.Number(default=0.0, bounds=(0.0, 2 * np.pi))
frequency = param.Number(default=1.0, bounds=(0.1, 5.1))
N = param.Integer(default=200, bounds=(0, None))
x_range = param.Range(default=(0, 4 * np.pi), bounds=(0, 4 * np.pi))
y_range = param.Range(default=(-2.5, 2.5), bounds=(-10, 10))

def __init__(self, **params):
super(SineWave, self).__init__(**params)
x, y = self.sine()
self.cds = ColumnDataSource(data=dict(x=x, y=y))
self.plot = figure(plot_height=400, plot_width=400,
tools="crosshair, pan, reset, save, wheel_zoom",
x_range=self.x_range, y_range=self.y_range)
self.plot.line('x', 'y', source=self.cds, line_width=3, line_alpha=0.6)

@param.depends('N', 'frequency', 'amplitude', 'offset', 'phase', 'x_range', 'y_range', watch=True)
def update_plot(self):
x, y = self.sine()
self.cds.data = dict(x=x, y=y)
self.plot.x_range.start, self.plot.x_range.end = self.x_range
self.plot.y_range.start, self.plot.y_range.end = self.y_range

def sine(self):
x = np.linspace(0, 4 * np.pi, self.N)
y = self.amplitude * np.sin(self.frequency * x + self.phase) + self.offset
return x, y
9 changes: 9 additions & 0 deletions examples/apps/fastApi_multi_apps/templates/app2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>Panel in FastAPI: sliders</title>
</head>
<body>
{{ script|safe }}
</body>
</html>
9 changes: 9 additions & 0 deletions examples/apps/fastApi_multi_apps/templates/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>Panel in FastAPI: sliders</title>
</head>
<body>
{{ script|safe }}
</body>
</html>
15 changes: 14 additions & 1 deletion examples/user_guide/Django_Apps.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,22 @@
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"pygments_lexer": "ipython3"
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3"
}
},
"nbformat": 4,
Expand Down
Loading

0 comments on commit 1351e7f

Please sign in to comment.