Introduction: What is Flet and Why Combine it with Web APIs?
Flet is a Python framework that enables developers to build interactive, multi-user web, desktop, and mobile applications using Flutter controls – all from a single Python codebase. Instead of writing JavaScript or Dart, you write Python and Flet translates it into a Flutter UI that runs in the browser or as a native app. "Web APIs" refer to HTTP-based interfaces (like REST or GraphQL) that allow your application to fetch or send data to external services. Combining Flet with Web APIs lets you create rich, real‑time dashboards, data viewers, or interactive tools that pull live information from the internet – for example, weather data, stock prices, GitHub repositories, or AI models. This guide will show you how to build a complete Flet web application that communicates with external Web APIs, covering everything from setup to best practices.
Setting Up Your Flet Environment
First, ensure you have Python 3.8 or later installed. Then install Flet and an HTTP client library. We'll use the popular httpx library because it supports both synchronous and asynchronous requests – essential for Flet's event loop.
pip install flet httpx
Create a new Python file, e.g., weather_app.py. We'll build a weather dashboard that fetches data from the OpenWeatherMap API. You'll need a free API key from openweathermap.org.
Making HTTP Requests in Flet
Flet apps run on an asynchronous event loop (asyncio). To avoid blocking the UI, you should make API calls asynchronously. The httpx library provides an AsyncClient for this purpose. Below is a simple function that fetches weather data for a given city.
import httpx
async def get_weather(city: str, api_key: str) -> dict:
url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric"
async with httpx.AsyncClient() as client:
response = await client.get(url)
response.raise_for_status() # Raise exception on HTTP error
return response.json()
Building the Weather Dashboard UI
Now we create the Flet app with a text field for the city name, a button to fetch weather, and controls to display temperature, humidity, and a weather icon. We'll use page.add() to build the UI incrementally. The key is to call await page.update_async() after changing the UI inside an asynchronous event handler.
import flet as ft
from flet import Page, TextField, ElevatedButton, Column, Text, Row, Image
async def main(page: Page):
page.title = "Weather Dashboard"
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.scroll = ft.ScrollMode.AUTO
# UI components
city_input = TextField(label="Enter city name", width=300)
fetch_btn = ElevatedButton("Get Weather", on_click=lambda e: page.run_task(fetch_weather))
weather_icon = Image(width=100, height=100)
temp_text = Text(size=24)
humidity_text = Text()
error_text = Text(color="red")
async def fetch_weather():
error_text.value = ""
weather_icon.src = ""
temp_text.value = ""
humidity_text.value = ""
city = city_input.value.strip()
if not city:
error_text.value = "Please enter a city name."
await page.update_async()
return
# Show loading indicator (optional)
fetch_btn.text = "Loading..."
fetch_btn.disabled = True
await page.update_async()
try:
data = await get_weather(city, "YOUR_API_KEY_HERE")
temp_c = data["main"]["temp"]
humidity = data["main"]["humidity"]
icon_code = data["weather"][0]["icon"]
icon_url = f"http://openweathermap.org/img/wn/{icon_code}@2x.png"
temp_text.value = f"{temp_c:.1f} °C"
humidity_text.value = f"Humidity: {humidity}%"
weather_icon.src = icon_url
except httpx.HTTPStatusError as e:
error_text.value = f"HTTP Error: {e.response.status_code}"
except Exception as e:
error_text.value = f"Error: {str(e)}"
finally:
fetch_btn.text = "Get Weather"
fetch_btn.disabled = False
await page.update_async()
# Assemble the layout
page.add(
Column(
controls=[
city_input,
fetch_btn,
weather_icon,
temp_text,
humidity_text,
error_text,
],
alignment=ft.MainAxisAlignment.CENTER,
spacing=20,
)
)
ft.app(target=main)
Running the App
Run the script with Python:
python weather_app.py
Flet will start a local web server (default: http://localhost:8550). Open it in your browser, type a city, and click "Get Weather". The UI updates asynchronously without freezing.
Handling Asynchronous API Calls Properly
Flet's event handlers (like on_click) are synchronous. To run async code, use page.run_task(coroutine) or asyncio.create_task(). The example above uses page.run_task inside a lambda. For more complex apps, consider separating API logic into a dedicated service module.
import asyncio
async def fetch_weather_wrapper():
await fetch_weather()
# Inside the button:
fetch_btn.on_click = lambda e: asyncio.create_task(fetch_weather_wrapper())
Best Practices for Building Web APIs with Flet
- Error Handling: Always wrap API calls in try/except blocks. Display user‑friendly error messages (e.g., "City not found" vs. a raw JSON error). Use
raise_for_status()to catch HTTP errors. - Loading State: Disable buttons and show a progress indicator (
ft.ProgressBar) during API calls to prevent duplicate requests and give feedback. - API Keys & Secrets: Never hard‑code API keys in your code. Use environment variables (
os.getenv("API_KEY")) or a configuration file. Add.envto your.gitignore. - Caching: If you fetch the same data frequently, cache results in memory (e.g., a dictionary with expiry) to reduce API calls and improve responsiveness.
- Rate Limiting: Respect API rate limits. Implement throttling or queue requests if needed. Use
time.sleep()between calls or a library likeaiolimiter. - Separation of Concerns: Keep API logic (HTTP calls, data parsing) separate from UI logic. Create a
servicesmodule with functions likeget_weatherand import them into your Flet app. - Use Async Everywhere: Flet is async‑first. Prefer
async deffor event handlers and useawait page.update_async()instead ofpage.update(). - Testing: Test API calls in isolation using
pytestwith mocking (e.g.,httpx_mock). This ensures your data parsing works correctly without hitting live endpoints.
Conclusion
Building Web APIs with Flet is a powerful way to create data‑driven web applications entirely in Python. By combining Flet's intuitive UI components with asynchronous HTTP requests, you can build interactive dashboards, real‑time monitors, and tools that pull live data from any RESTful service. This guide covered the essential steps: setting up the environment, making async HTTP calls, handling UI updates, and following best practices for error handling, loading states, and security. With these foundations, you can extend the example to integrate any public API – from social media to financial data – and deliver a smooth, Flutter‑powered experience without writing a single line of JavaScript.