Skip to content

Instantly share code, notes, and snippets.

@AnnMarieW
Created November 20, 2024 21:51
Show Gist options
  • Save AnnMarieW/cda90db92c56ca90934df4febec6fdd5 to your computer and use it in GitHub Desktop.
Save AnnMarieW/cda90db92c56ca90934df4febec6fdd5 to your computer and use it in GitHub Desktop.
FastAPI with Dash
from fastapi import FastAPI, Request
from pydantic import BaseModel
from typing import List, Dict, Any, Union, Optional
from dash import Dash, html, Input, Output, ctx, set_props
import dash
from flask import Flask, has_request_context
import flask
from flask.testing import EnvironBuilder
from werkzeug.datastructures import Headers
from werkzeug.wrappers import Request as WerkzeugRequest
import json
# Create a Flask server
flask_server = Flask(__name__)
# Create a FastAPI app
app = FastAPI()
def print_error(error):
print(error)
set_props('app_notifications', {'children': 'IT has been notified of the error'})
return dash.no_update
# Create a Dash app
dash_app = Dash(__name__, server=flask_server, routes_pathname_prefix='/dash/',
requests_pathname_prefix='/api/',
on_error=print_error)
# Define the layout of the Dash app
dash_app.layout = html.Div(children=[
html.H1(children='Hello Dash'),
html.Div(children='Dash: A web application framework for Python.'),
html.Button('Testing', id='test'),
html.Div(id='testout')
])
class Outputs(BaseModel):
id: Union[str, dict]
property: str
class Inputs(BaseModel):
id: Union[str, dict]
property: str
value: Optional[Any] = None
class States(BaseModel):
id: Union[str, dict]
property: str
value: Optional[Any] = None
class Payload(BaseModel):
output: str
outputs: Outputs
inputs: List[Inputs]
state: Optional[List[States]] = []
changedPropIds: List[Any]
parsedChangedPropsIds: List[Any]
@app.post('/_dash-update-component')
async def execute_callback(payload: Payload, request: Request):
# Create a WSGI environment from the FastAPI request
headers = [(key, value) for key, value in request.headers.items()]
environ_builder = EnvironBuilder(
flask_server,
method=request.method,
path=request.url.path,
headers=Headers(headers),
data=json.dumps(payload.model_dump()),
query_string=request.url.query.encode('utf-8')
)
flask.request = environ_builder.get_request()
response = dash_app.dispatch()
return response
@dash_app.callback(
Output('testout','children'),
Input('test','n_clicks')
)
@app.post('/test-click')
def rawr(n):
1/0
if has_request_context():
set_props('test', {'children': 'rawr'})
return n
return {"status": "ok", "data": n}
# Run the app with Uvicorn
if __name__ == "__main__":
import uvicorn
# Run the FastAPI app with Uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment