跳到主要内容

作为动态网站托管应用

介绍

Flet 实现了 FastAPI 应用程序来将您的应用程序运行为动态网站。

默认情况下,它使用 Uvicorn 网络服务器来运行应用程序,但也可以使用任何兼容 ASGI 的服务器。

同步和异步处理程序

在 Flet web 应用中,您可以在同一个应用中混合使用同步和异步方法。

例如,您可以编写如下应用:

import flet as ft
import time
import asyncio

def main(page: ft.Page):

def handler(e):
time.sleep(3)
page.add(ft.Text("Handler clicked"))

async def handler_async(e):
await asyncio.sleep(3)
page.add(ft.Text("Async handler clicked"))

page.add(
ft.ElevatedButton("Call handler", on_click=handler),
ft.ElevatedButton("Call async handler", on_click=handler_async)
)

ft.app(main)

在这个示例中,点击一个按钮由“阻塞”处理程序处理,而点击另一个按钮调用异步处理程序。第一个处理程序在 threading.Thread 中运行,而第二个处理程序作为 asyncio.Task 运行。

在 web 应用中,使用线程是应用扩展性的一个考虑因素,因为线程是有限资源。通常使用线程池,但随着用户数量的增加,它可能成为瓶颈。

无论如何,如果您的应用主要进行 I/O 操作(数据库、web API)并且/或者您能够使用支持异步的库,我们建议实现异步处理程序。

查看 FastAPI 关于 async/await 的文章以更好地了解并发性和并行性的区别。

本地运行应用

使用 --web (-w) 选项启动 Flet 应用作为 web 应用:

flet run --web app.py

将打开一个新的浏览器窗口/标签页,应用将使用随机 TCP 端口。

要在固定端口上运行,请使用 --port (-p) 选项:

flet run --web --port 8000 app.py

在生产环境中运行应用

您可以直接使用 python 命令运行程序:

python app.py

默认情况下使用 Uvicorn 网络服务器托管 web 应用。

如果 Flet 检测到应用在无头 Linux 环境(如 Docker 容器或 EC2 VM)中运行:

  1. 使用端口 8000 运行应用。
  2. 不会打开带有应用的浏览器窗口。

如果由于某种原因 Flet 无法检测到无头环境,您可以通过定义以下环境变量强制这种行为:

FLET_FORCE_WEB_SERVER=true

ASGI 网络服务器

您可以使用任何兼容 ASGI 的服务器托管您的 Flet web 应用,如默认使用的 UvicornHypercornDaphne

只需告诉 Flet 导出 ASGI 应用:

main.py
import flet as ft

def main(page: ft.Page):
page.add(ft.Text("Hello ASGI!"))

app = ft.app(main, export_asgi_app=True)

Hypercorn

Hypercorn 是另一个受 Gunicorn 启发的 ASGI 网络服务器。

使用 Hypercorn 运行应用:

hypercorn main:app --bind 0.0.0.0:8000

Daphne

Daphne 是一个用于 ASGI 和 ASGI-HTTP 的 HTTP、HTTP2 和 WebSocket 协议服务器,开发用于支持 Django Channels。

使用 Daphne 运行应用:

daphne -b 0.0.0.0 -p 8000 main:app

Gunicorn

Gunicorn 是运行 Python web 应用的流行网络服务器。虽然它实现了 WSGI 规范,但可以使用 Uvicorn 提供的工作进程类运行 ASGI FastAPI 应用:

gunicorn --bind 0.0.0.0:8000 -k uvicorn.workers.UvicornWorker counter:app

资源

当您在浏览器中打开 Flet 应用时,它的 index.html、Flutter 引擎、favicon、图片和其他 web 应用资源由网络服务器提供。这些资源与 flet Python 包一起打包。然而,有时您需要修改某些文件的内容以自定义应用的外观或行为,例如:

  • Favicon。
  • 应用加载动画。
  • 带有 PWA 详细信息的 manifest.json

您可以在 flet.app() 调用中指定 assets_dir 以设置应用可用的资源位置。assets_dir 应该是相对于 main.py 目录的相对路径或绝对路径。assets_dir 参数的默认值是 assets

例如,考虑以下程序结构:

/assets
/images/my-image.png
main.py

您可以在应用中按如下方式访问您的图片:

import flet as ft

def main(page: ft.Page):
page.add(ft.Image(src=f"/images/my-image.png"))

ft.app(main, assets_dir="assets")

自定义 web 应用

Favicon

要使用您自己的 favicon 覆盖默认的,将 favicon.png 文件放入资源目录的根目录。它应该是至少 32x32 像素的 PNG 图像。

加载动画

要用您的应用标志覆盖 Flet 动画图像,将 icons/loading-animation.png 图像放入资源目录的根目录。

PWA

渐进式 web 应用(PWA)提供了一种将类应用网站变成类网站应用的方法。

查看 PWAs Turn Websites Into Apps: Here's How 了解 PWA 的介绍。

支持 PWA 的浏览器(安装说明):

  • 所有平台上的 Chrome
  • 所有平台上的 Edge
  • Android 上的 Firefox
  • iOS 和 iPadOS 上的 Safari
信息

本节信息基于以下资源(查看更多详细信息):

Manifest

您可以在 manifest.json 中更改 PWA 的名称、描述、颜色和其他信息,必须将其放在 assets 目录的根目录。

以下是您可能希望自定义的最常见 manifest 项目的链接:

  • name - 通常显示给用户的 web 应用名称。
  • short_name - 如果没有足够空间显示 name,则显示给用户的 web 应用名称。
  • description - 解释应用程序的功能。
  • theme_color - 定义应用程序的默认主题颜色。
  • background_color - 定义在应用程序页面加载样式表之前显示的占位符背景颜色。
图标

自定义图标应放置在 assets/icons 目录中:

  • icon-192.pngicon-512.png - 显示在 Windows 任务栏中的应用图标。
  • icon-maskable-192.pngicon-maskable-512.png - 显示在 Android 中的应用图标。
  • apple-touch-icon-192.png - 显示在 iOS 中的应用图标。

环境变量

网络应用托管的每个方面都可以通过环境变量进行额外控制:

  • FLET_FORCE_WEB_SERVER - true 强制将应用程序作为 web 应用运行。在无头 Linux 主机上自动设置。
  • FLET_SERVER_PORT - 运行应用程序的 TCP 端口。如果程序在 Linux 服务器上运行或设置了 FLET_FORCE_WEB_SERVER,则为 8000;否则为随机端口。
  • FLET_SERVER_IP - 监听 web 应用的 IP 地址,例如 127.0.0.1。默认值为 0.0.0.0 - 绑定到所有服务器 IP。
  • FLET_ASSETS_DIR - 应用程序“assets”目录的绝对路径。
  • FLET_UPLOAD_DIR - 应用程序“upload”目录的绝对

路径。

  • FLET_MAX_UPLOAD_SIZE - 允许上传文件的最大大小(以字节为单位)。如果未指定,则为无限制。
  • FLET_SECRET_KEY - 签署临时上传 URL 的密钥。
  • FLET_WEB_APP_PATH - 主机 web 应用的域名后的 URL 路径,例如 /apps/myapp。默认值为 / - 在根目录中托管应用。
  • FLET_SESSION_TIMEOUT - 会话生命周期,以秒为单位。默认值为 3600
  • FLET_OAUTH_STATE_TIMEOUT - 完成 OAuth web 流程的最大允许时间,以秒为单位。默认值为 600
  • FLET_WEB_RENDERER - Flutter 渲染模式:canvaskit(默认)、htmlauto
  • FLET_WEB_USE_COLOR_EMOJI - trueTrue1 加载带有彩色表情符号的网络字体。
  • FLET_WEB_ROUTE_URL_STRATEGY - path(默认)或 hash
  • FLET_WEBSOCKET_HANDLER_ENDPOINT - WebSocket 处理程序的自定义路径。默认值为 /ws
  • FLET_UPLOAD_HANDLER_ENDPOINT - 上传处理程序的自定义路径。默认值为 /upload
  • FLET_OAUTH_CALLBACK_HANDLER_ENDPOINT - OAuth 处理程序的自定义路径。默认值为 /oauth_callback

高级 FastAPI 场景

Flet FastAPI 应用

flet.fastapi.app() 函数创建一个新的 FastAPI 应用程序来处理带有 session_handler 的会话,并在应用程序的根目录下挂载以下端点:

/ws (WS) - Flet 应用的 WebSocket 处理程序。当建立新的 WebSocket 连接并创建新应用会话时,它会调用 main() 函数。

/upload (PUT) - 文件上传处理程序。

/oauth_callback (GET) - OAuth 流程回调处理程序。

/ (GET) - 带有 SPA catch-all 处理程序的 Flet 应用静态文件。

flet.fastapi.app() 参数:

  • session_handler(函数或协程)- 应用程序入口点 - 为新连接的用户调用的方法。处理程序必须有一个参数:page - Page 实例。
  • assets_dir(str,可选)- 应用程序资源目录的绝对路径。
  • app_name(str,可选)- PWA 应用名称。
  • app_short_name(str,可选)- PWA 应用短名称。
  • app_description(str,可选)- PWA 应用描述。
  • web_renderer(WebRenderer)- 默认为 WebRenderer.CANVAS_KIT 的 web 渲染器。
  • use_color_emoji(bool)- 是否加载带有彩色表情符号的字体。默认值为 False
  • route_url_strategy(str)- 路由 URL 策略:path(默认)或 hash
  • upload_dir(str)- 上传文件目录的绝对路径。
  • max_upload_size(str, int)- 单个上传的最大大小(以字节为单位)。如果为 None 则为无限制。
  • secret_key(str,可选)- 签署和验证上传请求的密钥。
  • session_timeout_seconds(int,可选)- 用户断开连接后的会话生命周期(以秒为单位)。
  • oauth_state_timeout_seconds(int,可选)- OAuth 状态生命周期(以秒为单位),这是从开始 OAuth 流程到重定向到 OAuth 回调 URL 的最大允许时间。

在同一域名下托管多个 Flet 应用

import flet as ft
import flet.fastapi as 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))

子应用必须在根 Flet 应用之前映射,因为它为 SPA 配置了 catch-all index.html

使用 uvicorn 运行应用并访问 http://127.0.0.1:8000http://127.0.0.1:8000/sub-app/ 以查看两个 Flet 应用正在运行。

注意

注意 /sub-app/ URL 中的斜杠 - 没有斜杠的请求将路由到根应用。

将 Flet 添加到现有的 FastAPI 应用

from contextlib import asynccontextmanager

import flet as ft
import flet.fastapi as 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))

将 Flet 应用添加到现有的 FastAPI 应用时,您需要在应用启动时调用 flet_fastapi.app_manager.start(),在关闭时调用 flet_fastapi.app_manager.shutdown()。使用最适合您的方式:生命周期(在上面的示例中)或应用事件。

app_manager.start() 方法启动清理过期会话和 OAuth 流程状态的后台任务。

app_manager.shutdown() 方法删除 Flet 应用创建的任何临时文件。

配置单个 Flet 端点

静态文件

一个 FastAPI 应用来提供静态 Flet 应用文件(index.html、manifest.json、Flutter JS 应用等)和用户资源。

from flet.fastapi import FastAPI, FletStaticFiles

app = FastAPI()

# 挂载到 web 应用的根目录
app.mount(path="/", app=FletStaticFiles())

FletStaticFiles 构造函数的参数:

  • app_mount_path(str)- Flet 应用的绝对 URL。默认值为 /
  • assets_dir(str,可选)- 应用程序资源目录的绝对路径。
  • app_name(str,可选)- PWA 应用名称。
  • app_short_name(str,可选)- PWA 应用短名称。
  • app_description(str,可选)- PWA 应用描述。
  • web_renderer(WebRenderer)- 默认为 WebRenderer.CANVAS_KIT 的 web 渲染器。
  • use_color_emoji(bool)- 是否加载带有彩色表情符号的字体。默认值为 False
  • route_url_strategy(str)- 路由 URL 策略:path(默认)或 hash
  • websocket_endpoint_path(str,可选)- Flet 应用 WebSocket 处理程序的绝对 URL。默认值为 {app_mount_path}/ws

WebSocket 处理程序

处理来自浏览器中运行的 Flet 客户端应用的 WebSocket 连接。WebSocket 通道用于将事件从浏览器发送到 Flet 后端代码并接收页面实时增量更新。

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(协程)- 应用程序入口点 - 为新连接的用户调用的异步方法。处理程序协程必须有一个参数:page - Page 实例。
  • session_timeout_seconds(int,可选)- 用户断开连接后的会话生命周期(以秒为单位)。
  • oauth_state_timeout_seconds(int,可选)- OAuth 状态生命周期(以秒为单位),这是从开始 OAuth 流程到重定向到 OAuth 回调 URL 的最大允许时间。
  • upload_endpoint_path(str,可选)- 上传端点的绝对 URL,例如 /upload
  • secret_key(str,可选)- 签署上传请求的密钥。

上传处理程序

处理 FilePicker 控件的文件上传。此端点是可选的 - 如果您的应用不使用 FilePicker,则不需要它。

from flet.fastapi import FletUpload

@app.put("/upload")
async def flet_uploads(request: Request):
await FletUpload("/Users/feodor/Downloads/123").handle(request)

OAuth 回调处理程序

处理 OAuth 流程回调请求。如果您的应用不使用[身份验证

](/docs/cookbook/authentication),则不需要此端点。

from flet.fastapi import FletOAuth

@app.get("/oauth_callback")
async def flet_oauth(request: Request):
return await FletOAuth().handle(request)