Running Flet with FastAPI
Flet for FastAPI replaces built-in Flet web server (Fletd) when deploying your Flet web apps to production. FastAPI app run by Uvicorn, Hypercorn or industry-leading Gunicorn web server enables you to build reliable, high-performant Flet applications.
Existing FastAPI developers can use Flet to easily add interactive, real-time dashboards to their FastAPI apps.
Installation
To install flet-fastapi
run the following command:
pip install flet-fastapi
Example app
Flet app (and its dependent libraries) must be async to be able to run within FastAPI. Check this article to learn how to write async Flet apps and we also recommend reading FastAPI's article about async/await to better understand the differences between concurrency and parallelism.
Create counter.py
with the following content:
import flet as ft
import flet_fastapi
async def main(page: ft.Page):
counter = ft.Text("0", size=50, data=0)
async def add_click(e):
counter.data += 1
counter.value = str(counter.data)
await counter.update_async()
page.floating_action_button = ft.FloatingActionButton(
icon=ft.icons.ADD, on_click=add_click
)
await page.add_async(
ft.Container(counter, alignment=ft.alignment.center, expand=True)
)
app = flet_fastapi.app(main)
That's a simple app displaying a counter and a button at the right bottom of the page to increment that counter.
Running the app locally
Install Uvicorn web server:
pip install uvicorn
Start uvicorn
with:
uvicorn counter:app
Open the browser and navigate to http://127.0.0.1:8000 to see the app running.
How it works
flet_fastapi.app()
configures a single Flet app at the root of FastAPI app with main()
sessions handler and the following endpoints:
/ws
(WS) - WebSocket handler for the Flet app. It calls main()
function when a new WebSocket connection established and a new app session created.
/upload
(PUT) - file uploads handler.
/oauth_callback
(GET) - OAuth flow callback handler.
/
(GET) - Flet app static files with SPA catch-all handler.
flet_fastapi.app()
parameters:
fastapi_app
(FastAPI) - FastAPI application instance.session_handler
(Coroutine) - application entry point - an async method called for newly connected user. Handler coroutine must have 1 parameter:page
-Page
instance.assets_dir
(str, optional) - an absolute path to app's assets directory.app_name
(str, optional) - PWA application name.app_short_name
(str, optional) - PWA application short name.app_description
(str, optional) - PWA application description.web_renderer
(WebRenderer) - web renderer defaulting toWebRenderer.CANVAS_KIT
.use_color_emoji
(bool) - whether to load a font with color emoji. Default isFalse
.route_url_strategy
(str) - routing URL strategy:path
(default) orhash
.upload_dir
(str) - an absolute path to a directory with uploaded files.max_upload_size
(str, int) - maximum size of a single upload, bytes. Unlimited ifNone
.secret_key
(str, optional) - secret key to sign and verify upload requests.session_timeout_seconds
(int, optional)- session lifetime, in seconds, after user disconnected.oauth_state_timeout_seconds
(int, optional) - OAuth state lifetime, in seconds, which is a maximum allowed time between starting OAuth flow and redirecting to OAuth callback URL.
Hosting multiple Flet apps under the same domain
import flet as ft
import flet_fastapi
async def root_main(page: ft.Page):
await page.add_async(ft.Text("This is root app!"))
async def sub_main(page: ft.Page):
await page.add_async(ft.Text("This is sub app!"))
app = flet_fastapi.FastAPI()
app.mount("/sub-app", flet_fastapi.app(sub_main))
app.mount("/", flet_fastapi.app(root_main))
Sub-apps must be mapped before the root Flet app as it configures catch-all index.html
for SPA.
Run the app with uvicorn
and visit http://127.0.0.1:8000 and then http://127.0.0.1:8000/sub-app/ to see both Flet apps running. Notice the trailing slash in /sub-app/
URL - without the slash the request will be routed to a root app.
Adding Flet to the existing FastAPI app
from contextlib import asynccontextmanager
import flet as ft
import flet_fastapi
from fastapi import FastAPI
@asynccontextmanager
async def lifespan(app: FastAPI):
await flet_fastapi.app_manager.start()
yield
await flet_fastapi.app_manager.shutdown()
app = FastAPI(lifespan=lifespan)
async def main(page: ft.Page):
await page.add_async(ft.Text("Hello, Flet!"))
app.mount("/flet-app", flet_fastapi.app(main))
When adding Flet app to the existing FastAPI app you need to call flet_fastapi.app_manager.start()
on app start and flet_fastapi.app_manager.shutdown()
on shutdown. Use the way that best suites you: lifespan (in the example above) or app events.
app_manager.start()
method starts background tasks cleaning up expired sessions and OAuth flow states.
app_manager.shutdown()
method removes any temporary files created by a Flet app.
Configuring individual Flet endpoints
Static files
A FastAPI app to serve static Flet app files (index.html, manifest.json, Flutter JS app, etc.) and user assets.
from flet_fastapi import FastAPI, FletStaticFiles
app = FastAPI()
# mount to the root of web app
app.mount(path="/", app=FletStaticFiles())
Parameters of FletStaticFiles
constructor:
app_mount_path
(str) - absolute URL of Flet app. Default is/
.assets_dir
(str, optional) - an absolute path to app's assets directory.app_name
(str, optional) - PWA application name.app_short_name
(str, optional) - PWA application short name.app_description
(str, optional) - PWA application description.web_renderer
(WebRenderer) - web renderer defaulting toWebRenderer.CANVAS_KIT
.use_color_emoji
(bool) - whether to load a font with color emoji. Default isFalse
.route_url_strategy
(str) - routing URL strategy:path
(default) orhash
.websocket_endpoint_path
(str, optional) - absolute URL of Flet app WebSocket handler. Default is{app_mount_path}/ws
.
WebSocket handler
Handles WebSocket connections from Flet client app running in the browser. WebSocket channel is used to send events from a browser to a Flet backend code and receive page real-time incremential updates.
from flet_fastapi import FletApp
async def main(page: ft.Page):
await page.add_async(ft.Text("Hello, Flet!"))
@app.websocket("/app1/ws")
async def flet_app(websocket: WebSocket):
await FletApp(main).handle(websocket)
session_handler
(Coroutine) - application entry point - an async method called for newly connected user. Handler coroutine must have 1 parameter:page
-Page
instance.session_timeout_seconds
(int, optional) - session lifetime, in seconds, after user disconnected.oauth_state_timeout_seconds
(int, optional) - OAuth state lifetime, in seconds, which is a maximum allowed time between starting OAuth flow and redirecting to OAuth callback URL.upload_endpoint_path
(str, optional) - absolute URL of upload endpoint, e.g./upload
.secret_key
(str, optional) - secret key to sign upload requests.
Uploads handler
Handles file uploads by FilePicker control. This endpoint is optional - if your app doesn't use FilePicker then it's not needed.
from flet_fastapi import FletUpload
@app.put("/upload")
async def flet_uploads(request: Request):
await FletUpload("/Users/feodor/Downloads/123").handle(request)
OAuth callback handler
Handles OAuth flow callback requests. If your app does't use authentication then this endpoint is not needed.
from flet_fastapi import FletOAuth
@app.get("/oauth_callback")
async def flet_oauth(request: Request):
return await FletOAuth().handle(request)
Running the app in production
Uvicorn
Uvicorn, a lightning-fast ASGI server, built on uvloop and httptools.
To install Uvicorn:
pip install uvicorn
To run the app with Uvicorn while listening on all NIC IPs and port 8000
:
uvicorn --host 0.0.0.0 --port 8000 main:app
Hypercorn
Hypercorn is another ASGI web server inspired by Gunicorn.
To install Hypercorn:
pip install hypercorn
To run the app with Hypercorn:
hypercorn --bind 0.0.0.0:8000 main:app
Gunicorn
Gunicorn is popular web server to run Python web applications. While it implements WSGI specification it's possible to run ASGI FastAPI apps with a worker process class provided by Uvicorn.
To install Gunicorn:
pip install gunicorn
Start gunicorn
with:
gunicorn --bind 0.0.0.0:8000 -k uvicorn.workers.UvicornWorker counter:app