The first step to get it added to the Panel docs would be to open a feature request on GitHub.
I think it would be helpful if you describe one or more ways it could be added in the request.
My main question is if the Panel docs mainly should refer to your doc and example or whether the example should be included in the gallery of Panel. Personally I think it makes sense to add it similarly to adding flask and django examples.
Really great writeup @t-houssian! Agree with Marc. I’d probably like to have some form of nesting of the TOC tree in the user guide and then put Flask, Django and Fast API guides under a header about “Embedding Panel Apps”. Let’s start with a PR and then we can iterate.
Thanks for the response and feedback! As for your questions:
For this example I used a thread. I tried using panel serve at first but couldn’t quite get that working, any pointers on what I’d need to do?
Our case for using fastApi with panel is to embed the panel app in our internal automation app that we’ve been building out with fastApi. We wanted to keep using fastApi to take advantage of it’s speed and extensive framework, but also wanted to use the data visualization tools in panel.
I didn’t realize their was a panel server class in panel. I will have to check that out.
Maybe could you help me re-write this part to use panel instead of bokeh:
if two people access the same dashbaord on their browsers they work asynchronously.
i.e. if one access any page on its browser other person’s dashboard which is loaded in browser updated to same page
Hi @khannaum I’m glad you were able to get this up and running. I ran into a similar issue a little bit ago when using a django server with panel. For me the issue came from using widgets as class variables. I had to only use params as class variables within my Parameterized class. Could you share what your code looks like in your panel.py files?
@khannaum Thanks for sharing your code. It looks like in your cust_mapping function there you will need to change your widgets that are set to variables like here
To get the same functionality.
I think after converting some of your widgets into params and possibly using a parameterized class that might help your mutliple users problem (At least for me it did). Check out the guide on this example to maybe get some ideas on refactoring your code. https://panel.holoviz.org/gallery/param/reactive_tables.html#param-gallery-reactive-tables
Seems like there are already solutions here, but, FWIW, I’m accomplishing something similar using Nginx as a reverse proxy:
nginx.conf
events {}
http {
server {
listen 1001; # The port where clients should connect
location /api/ { # forward requests with this prefix to FastAPI (or any other app)
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:1002; # The other app should be listening here
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
}
location / { # forward the rest to Panel
proxy_pass http://127.0.0.1:1003; # Panel should be listening here
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_redirect off;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
}
For FastAPI, you’ll have to set the root_path to /api.
If running in something like Docker, it might also be helpful to use something like supervisord to manage all three processes:
supervisord.conf
[supervisord]
user = root
nodaemon = true # this expects supervisord to be run as the main command in a Docker container
logfile = /dev/null # don't log to a file - only stdout/stderr
logfile_maxbytes = 0 # disable log file rotation
[program:fastapi]
command = gunicorn --bind 0.0.0.0:1002 ... # However you want to run FastAPI
startsecs = 5
autostart = true
autorestart = true
stopwaitsecs = 300
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0 # disable log file rotation
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0 # disable log file rotation
[program:panel]
command = panel serve --port 1003 --allow-websocket-origin ... # However you want to run Panel
startsecs = 5
autostart = true
autorestart = true
stopwaitsecs = 300
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0 # disable log file rotation
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0 # disable log file rotation
[program:nginx]
command = nginx -c /path/to/nginx.conf -g 'daemon off;'
startsecs = 5
autostart = true
autorestart = true
stopwaitsecs = 300
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0 # disable log file rotation
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0 # disable log file rotation
Might be more moving parts and more processes to monitor… but I imagine it should work for any framework, not just FastAPI.
My app has a large amount of shared state. This particular piece of data is purely read-only, and needs to be read exactly once. Ideally, I would read and cache it during the startup of the FastAPI server, and then reuse it for all apps and all documents.
Of course, my app also has a smaller amount of dynamic things to do, which do not need to be in the shared state.
Now, here is my problem. I started up the panel server with pn.serve, as described. But I do not know how to pass a reference to the shared state from the main FastAPI startup code to the panel createApp function.
I did find a workaround: I put the createApp function in a separate python file and did initializations in it’s global space, before the createApp function definition. This works!
But it only allows me to create global variables for the panel server’s createApp function, and I may need the global variables to be available to some of my other FastAPI-based functionality.