Vai al contenuto principale

Python FastHTML: guida per principianti con esempi

Scopri FastHTML, una libreria Python per creare pagine web dinamiche. Include esempi di applicazioni reali.
· 15 min leggi

Scopri con l'IA

Costruire interfacce web moderne in Python spesso significa destreggiarsi tra più livelli, motori di templating, tool JavaScript e framework front-end, solo per far funzionare una UI di base. FastHTML offre un approccio più mirato: un framework minimale, Python-first, che semplifica lo sviluppo permettendoti di definire le interfacce direttamente nel codice, senza uscire dal linguaggio o gestire complessità extra.

Questo articolo esplora come funziona FastHTML, i suoi principi di progettazione fondamentali e come costruire applicazioni reali con esso—da pagine semplici a interfacce interattive e guidate dai dati.

Se vuoi consolidare le basi dello sviluppo backend prima di iniziare, ti consiglio di dare un'occhiata a questo tutorial sullo sviluppo backend in Python su DataCamp per una panoramica dei concetti e degli strumenti web principali.

Che cos'è FastHTML?

FastHTML è un framework Python snello progettato per semplificare lo sviluppo di interfacce web. Affronta sfide comuni in ambito di sviluppo, testing e prestazioni eliminando la necessità di una conoscenza approfondita di JavaScript o di gestire più file template.

Molti sviluppatori Python vogliono creare interfacce web senza doversi addentrare nelle complessità di uno stack JavaScript completo. FastHTML risponde a questa esigenza, consentendo di definire route e componenti HTML con poche, concise righe di codice Python.

Oltre alle interfacce di base, è facile estendere le applicazioni costruite con FastHTML incorporando funzionalità come autenticazione, caching, integrazione con database e styling personalizzato, migliorando notevolmente funzionalità ed esperienza utente.

Funzionalità e vantaggi di FastHTML

FastHTML ha molte funzionalità e vantaggi. Supera numerose sfide legate a sviluppo, testing e prestazioni.

FastHMTL ha molte funzionalità e vantaggi.

  • Sviluppo solo in Python: non ti serve funzionalità JavaScript aggiuntiva, solo Python. Il risultato sono progetti leggeri con meno file e meno boilerplate.
  • Dipendenze minime: FastHTML si basa su poche librerie esterne, quindi gli aggiornamenti sono semplici e la manutenzione è meno complessa.
  • Sicurezza. Meno dipendenze significa una superficie d'attacco più piccola. 
  • Stack client/server unificato: usare un solo linguaggio e framework per logica e UI riduce il context switching, accelerando lo sviluppo.
  • Elementi HTML come oggetti Python nativi: FastHTML ti permette di usare elementi HTML come oggetti Python tramite attributi HTMX, senza JavaScript personalizzato.
  • Gestione asincrona delle richieste: FastHTML supporta l'elaborazione asincrona delle richieste, con bassa latenza e alta concorrenza.
  • Deployment flessibile: Le applicazioni finite possono essere distribuite su qualsiasi piattaforma che supporti Python.

FastHTML riduce la complessità tipicamente associata allo sviluppo di UI web, come la gestione di file template separati, script di supporto e pipeline di asset. Anche il testing è notevolmente semplificato, poiché lo stack Python unificato permette di snellire le fasi di validazione backend, frontend ed end-to-end.

Principi architetturali di base

FastHTML si basa su principi architetturali fondamentali: il layer di astrazione HTML pythonico, l'integrazione con lo standard ASGI e l'interattività guidata da HTMX.

Layer di astrazione HTML pythonico

FastHTML rappresenta ogni elemento HTML standard come una corrispondente funzione Python. Per esempio, il tag HTML <div> è rispecchiato dalla funzione Python Div(...), <a> diventa A(..., href=...) e così via. 

Gli argomenti posizionali passati alle funzioni degli elementi Python vengono renderizzati come elementi figli nella struttura HTML risultante. Per esempio,

Div(
	P("Hello, world!"),
	Ul(Li("one"), Li("two"))
)

produrrà questo output HTML: 

<div>
  <p>Hello, world!</p>
  <ul>
    <li>one</li>
    <li>two</li>
  </ul>
</div>

Gli argomenti keyword diventano attributi HTML. Ad esempio, il codice Python

A("Docs", href="/docs", cls="button", hx_get="/info")

viene renderizzato in

<a href="/docs" class="button" hx-get="/info">Docs</a>

Nota che la keyword cls mappa sull'attributo class in HTML. I trattini bassi nei nomi degli attributi (hx_get) vengono convertiti in trattini (hx-get). 

FastHTML differisce la serializzazione, il che consente alle route di restituire oggetti Python invece di stringhe HTML grezze. Il framework converte l'albero di oggetti Python in HTML solo all'ultimo passaggio, appena prima di inviare la risposta. Questo design mantiene la logica pulita e libera da manipolazioni manuali di stringhe.

FastHTML offre i vantaggi di un templating type-safe e della gestione degli attributi, producendo codice più chiaro e manutenibile. Le API degli elementi e gli attributi compaiono nelle definizioni di funzioni o classi, rendendo il codice autoesplicativo. Nomi sicuri per Python (da hx-post a hx_post) evitano la necessità di manipolare manualmente stringhe.

Il refactoring è più sicuro e affidabile. Rinominare un parametro aggiorna automaticamente gli utilizzi. Inoltre, i test unitari possono istanziare e validare direttamente gli oggetti componente, evitando di dover ricorrere a regex sull'HTML renderizzato.

Integrazione con ASGI (Asynchronous Server Gateway Interface)

FastHTML si integra con ASGI, uno standard guidato dalla community per Python che abilita una comunicazione non bloccante ed event-driven tra web server e applicazioni. ASGI alimenta i framework web Python moderni supportando operazioni asincrone al cuore dello stack web.

Web server come Uvicorn aderiscono alle specifiche ASGI, garantendo compatibilità e scalabilità. Framework come Starlette e FastHTML si basano su ASGI per offrire routing robusto, middleware e API di alto livello.

Questa architettura offre alta concorrenza, supporto integrato per HTTP, WebSocket ed eventi inviati dal server, e una gestione efficiente e event-driven delle richieste. Usando un event loop asyncio, le app ASGI evitano l'overhead di un thread OS per connessione, consentendo a pochi thread di gestire migliaia di client. L'oggetto scope standardizzato e il design non bloccante permettono ai handler di mettersi in attesa per I/O senza rallentare le altre richieste.

Interattività guidata da HTMX

Con la libreria HTMX, puoi estendere gli attributi HTML standard con attributi hx-*. Questi elementi consentono di inviare richieste HTTP e sostituire dinamicamente il contenuto della pagina con frammenti restituiti dal server. Non serve JavaScript personalizzato. 

Iniziare con FastHTML

Iniziare con FastHTML è semplice. Di seguito abbiamo descritto i passaggi principali. 

Installazione e setup

Per installare FastHTML, usa pip install python-fasthtml.

Prima app

Costruiamo una semplice app per mostrare un'intestazione e un messaggio.

from fasthtml.common import FastHTML, serve, Div, H1, P

app = FastHTML()

@app.get("/")
def home():
    return Div(
        H1("Welcome to FastHTML"),
        P("Hello, world!")
    )

if __name__ == "__main__":
    serve()

Esegui il file digitando python app.py nel terminale. 

 

Fai Ctrl+clic sul link per aprire la tua app. Vedrai una pagina:

Definire una route

Aggiungiamo una pagina About alla nostra app. Usa il seguente codice:

from fasthtml.common import FastHTML, serve, Div, H1, P, A

app = FastHTML()

@app.get("/")
def home():
    return Div(
        H1("Welcome to FastHTML"),
        P("Hello, world!"),
        A("About", href="/about")
    )

@app.get("/about")
def about():
    return Div(
        H1("About"),
        P("This is the about page."),
        A("Home", href="/")
    )

if __name__ == "__main__":
    serve()

La riga A("About", href="/about") crea un link dalla home page alla pagina about. Il decorator @app.get("/about") definisce la route per la pagina about.

Implementazione di base

In FastHTML, i pattern UI riutilizzabili sono incapsulati in semplici funzioni Python. Queste funzioni restituiscono oggetti componente annidati, consentendoti di trattare widget come una Card o una Navbar come oggetti richiamabili. 

Definire markup, attributi e styling in un unico posto garantisce coerenza in tutta l'applicazione. Quando importi e usi queste funzioni, qualsiasi modifica visiva o comportamentale si propaga automaticamente. 

Questo approccio riduce il codice ripetuto, rendendo il tuo frontend facile da testare e rifattorizzare come qualsiasi modulo Python.

Per dimostrarlo, creiamo una pagina che mostra due semplici card.

from fasthtml.common import *

def Card(title: str, body: str):
    children = [
        H2(title, cls="card-title"),
        P(body, cls="card-body")
    ]
    return Div(
        *children,
        cls="card",
        style="background- border-radius: 0.5rem;"
    )

app = FastHTML()

@app.get("/")
def home():
    return Div(
        Card("Welcome", "A welcome card."),
        P(''),
        Card("A Second Card", "This is another card."),
        cls="page"
    )

La funzione Card accetta due stringhe, title e body, come argomenti e restituisce un elemento card con uno styling di base. Nella route home, questo widget viene usato due volte senza duplicare il codice. Definiamo la Card una sola volta e la riutilizziamo quando serve, assicurando markup e styling coerenti in tutta l'app.

Creare widget UI in questo modo offre diversi vantaggi.

  • Riduzione della duplicazione: imposti markup e styling una volta sola e riutilizzi il componente ovunque serva. Aggiornamenti o fix si propagano automaticamente.
  • Design UI coerente: ogni istanza del componente mantiene la stessa struttura, le stesse classi e lo stesso comportamento. Questo rafforza un look and feel uniforme in tutta l'applicazione.
  • Manutenzione semplificata: una codebase più piccola e DRY significa meno file da gestire, meno boilerplate e uno sviluppo più efficiente.

Uso avanzato

Questa sezione esplora tecniche avanzate in FastHTML, tra cui gestione dei form, validazione e pattern di feedback sugli errori. Sfruttando classi Python e componenti strutturati, puoi costruire form robusti e user-friendly mantenendo codice pulito e testabile.

Gestione dei form e validazione

FastHTML semplifica la gestione dei form generando automaticamente HTML a partire da classi Python e fornendo un data binding lineare per elaborare gli invii dei form. 

Per esempio, considera il seguente codice.

from fasthtml.common import *
from dataclasses import dataclass

@dataclass
class Profile:
    name:str;
    email:str;
    age:int

profile_form = Form(method="post", action="/profile")(
        Fieldset(
            Label("Name", Input(name="name")),
            Label("Email", Input(name="email")),
            Label("Age", Input(name="age")),
        ),
        Button("Submit", type="submit"),
    )

# Instantiate app
app = FastHTML()

# GET / serves the form (FastHTML will serialize the component to HTML)
@app.get("/")
def home():
    return profile_form

# Simple POST handler to echo back submitted data
@app.post("/profile")
def profile(data: Profile):
    return Div(
        H1("Profile Submitted"),
        P(f"Name: {data.name}"),
        P(f"Email: {data.email}"),
        P(f"Age: {data.age}")
    )

Questo codice genera il seguente HTML per il form. FastHTML analizza automaticamente i dati del form nell'oggetto Profile, supponendo nomi di campo compatibili. Sotto il cofano, ciò può basarsi su parsing in stile Starlette e su un layer di validazione personalizzato.

<form enctype="multipart/form-data" method="post" action="/profile">
	<fieldset>
	<label>Name<input name="name"></label>
	<label>Email<input name="email"></label>
	<label>Age<input name="age"></label>
</fieldset>

	<button type="submit">Submit</button>
</form>

Una volta inviato il form, FastHTML analizza i dati del form nell'oggetto Profile. La route profile quindi restituisce una pagina di conferma, mostrando i valori inviati direttamente dall'oggetto data. Questo approccio semplifica la gestione dei form, riduce il boilerplate e garantisce un forte typing dei dati in tutta l'applicazione.

È sempre una buona idea validare gli input del form. Aggiungi logica di validazione riscrivendo la route /profile come segue.

@app.post("/profile")
def submit_profile(data: Profile):
    # Form validation
    if not data.name.strip():
        raise HTTPException(status_code=400, detail="Name is required")
    if not data.email.strip() or "@" not in data.email:
        raise HTTPException(status_code=400, detail="A valid email is required")
    if data.age < 0:
        raise HTTPException(status_code=400, detail="Age must be non-negative")
    
    # If validation passes, render the result
    return Div(
        H1("Profile Submitted"),
        P(f"Name: {data.name}"),
        P(f"Email: {data.email}"),
        P(f"Age: {data.age}")
    )

Se name manca, email manca o age è negativo, l'utente riceve un messaggio di errore chiaro. Sollevando un'HTTPException con status code 400, l'applicazione comunica lo specifico errore di validazione, aiutando l'utente a correggere l'input prima di inviare di nuovo il form.

Un modo più robusto di gestire dati mancanti o non validi è effettuare controlli di errore espliciti e fornire feedback user-friendly. Ad esempio, riscrivi il codice come segue.

from fasthtml.common import *
from dataclasses import dataclass

@dataclass
class Profile:
    name: str
    email: str
    age: int

def profile_form(data=None, errors=None):
    data   = data   or {}
    errors = errors or {}
    return Form(
        Fieldset(
            Label(
                "Name",
                Input(
                    name="name",
                    value=data.get("name", ""),
                    placeholder="Your name"
                )
            ),
            Small(errors.get("name", ""), cls="error-text"),

            Label(
                "Email",
                Input(
                    name="email",
                    type="email",
                    value=data.get("email", ""),
                    placeholder="[email protected]"
                )
            ),
            Small(errors.get("email", ""), cls="error-text"),

            Label(
                "Age",
                Input(
                    name="age",
                    type="number",
                    value=str(data.get("age", "")),
                    placeholder="Age"
                )
            ),
            Small(errors.get("age", ""), cls="error-text"),
        ),
        Button("Submit", type="submit")
    , method="post", action="/profile", id="profile-form", hx_swap="outerHTML")

app = FastHTML()

@app.get("/")
def home():
    return Div(
        H1("Create Your Profile"),
        profile_form()
    )

@app.post("/profile")
async def submit_profile(request):
    form = await request.form()
    data = {
        "name":  form.get("name", "").strip(),
        "email": form.get("email", "").strip(),
    }
    errors = {}

    # Validate name
    if not data["name"]:
        errors["name"] = "Name is required. "

    # Validate email
    if not data["email"]:
        errors["email"] = "Email is required. "
    elif "@" not in data["email"]:
        errors["email"] = "Enter a valid email address."

    # Validate age
    age_raw = form.get("age", "").strip()
    try:
        age = int(age_raw)
        if age < 0:
            raise ValueError()
        data["age"] = age
    except ValueError:
        errors["age"] = "Age must be a non-negative integer. "

    if errors:
        # re-render form with submitted values and error messages
        return Div(
            H1("Create Your Profile"),
            profile_form(data, errors)
        )

    # Success path
    profile = Profile(**data)
    return Div(
        H1("Profile Submitted"),
        P(f"Name: {profile.name}"),
        P(f"Email: {profile.email}"),
        P(f"Age: {profile.age}")
    )

if __name__ == "__main__":
    serve()

Se l'utente salta un campo obbligatorio o fornisce un input non valido, vedrà il form renderizzato di nuovo con i valori inviati e gli opportuni messaggi di errore accanto a ciascun campo. Questo approccio migliora l'esperienza utente indicando chiaramente cosa va corretto.

Una volta compilati tutti i campi e inviato, otterrai una schermata simile alla seguente.

Autenticazione e gestione della sessione

Implementare i flussi di autenticazione

In FastHTML, i dati di sessione sono gestiti tramite l'oggetto request.session, che si comporta come un dizionario Python. Puoi memorizzare dati nella sessione impostando coppie chiave-valore, ad esempio session['user_id'] = 123. Per recuperare i dati di sessione, usa read (user_id = session.get('user_id')). Per cancellare tutti i dati di sessione, chiama session.clear().

Dietro le quinte, FastHTML serializza il dizionario di sessione in un cookie firmato, che persiste tra le richieste. Questo approccio ti permette di gestire autenticazione utente e stato di sessione usando pattern Python familiari.

Schema per costruire workflow di autenticazione

Per costruire un workflow di autenticazione, segui questi passaggi.

  1. Configura le sessioni: aggiungi SessionMiddleware con una secret_key robusta. Una volta configurato, request.session è disponibile in ogni handler.
  2. Modello utente e gestione password: definisci uno schema utente (usando dataclass, modello Pydantic o ORM) che includa uno username e password_hash. Usa una funzione di hashing (ad es. hashlib, pbkdf2_hmac, bcrypt) per memorizzare e verificare le password.
  3. Flusso di registrazione*: crea una route GET /register per mostrare un form di signup. * Usa POST /register per validare l'input del form, fare l'hash della password, salvare il record utente, impostare session['user_id'] e reindirizzare a una pagina protetta o alla dashboard.
  4. Flusso di login*: crea una route GET /login per mostrare il form di login.* Usa POST /login per verificare le credenziali. In caso di successo, scrivi session['user_id'] e reindirizza; in caso di fallimento, renderizza di nuovo il form con un messaggio di errore.
  5. Protezione delle route: crea una funzione helper o un decorator che controlli session.get('user_id'). Se l'utente non è autenticato, reindirizza a /login; altrimenti consenti l'accesso alla route richiesta.
  6. Flusso di logout: nella route GET /logout, chiama session.clear()` per rimuovere i dati di sessione e reindirizzare l'utente alla pagina di login o alla home.

Integrazione con database

Un Object-Relational Mapper (ORM) mappa le classi alle tabelle del database, permettendoti di interrogare i dati usando oggetti nativi invece di SQL grezzo. Opzioni popolari includono SQLAlchemy e l'ORM di Django. 

FastHTML ha un'interfaccia "simile a un ORM" che si integra con qualsiasi ORM o libreria di query Python compatibile con async. Di default usa SQLite ma può integrarsi con qualsiasi backend di database. Per esempio, considera il seguente codice.

# Database setup (SQLite by default, but backend can change)
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker, declarative_base
from sqlalchemy import Column, Integer, String, select
from fasthtml.common import *

DATABASE_URL = "sqlite+aiosqlite:///./test.db"  # Change backend here (e.g., PostgreSQL)

engine = create_async_engine(DATABASE_URL, echo=True)
SessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
Base = declarative_base()

# ORM model
class User(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True)
    name = Column(String)

# FastHTML app
app = FastHTML()

@app.get("/")
async def list_users():
    async with SessionLocal() as session:
        result = await session.execute(select(User))
        users = result.scalars().all()
    
    return Div(
        H1("Users"),
        Ul(*[Li(user.name) for user in users])
    )

if __name__ == "__main__":
    import asyncio
    async def init_db():
        async with engine.begin() as conn:
            await conn.run_sync(Base.metadata.create_all)
    asyncio.run(init_db())
    serve()

In un'applicazione FastHTML, interroghi i dati nello strato di database che preferisci, quindi passi i risultati ai componenti FastHTML per il rendering. Ad esempio, dopo aver recuperato i record dal database, puoi iterarli in un route handler e costruire strutture HTML come tabelle, liste o card personalizzate.

Le best practice restano valide: seleziona solo i campi necessari, filtra e ordina a livello di database e pagina risultati di grandi dimensioni. FastHTML ti aiuta a concentrarti sulla costruzione di front-end puliti e dinamici lasciando la gestione dei dati agli strumenti migliori per il tuo progetto.

Strategie di ottimizzazione delle prestazioni

Ci sono diversi modi per ottenere i migliori risultati con FastHTML. Di seguito abbiamo raccolto alcuni consigli. 

Meccanismi di caching

Il caching migliora le prestazioni evitando lavoro ridondante a diversi livelli dell'applicazione. A livello di browser e CDN, usa gli header di cache control per trattenere asset statici come immagini, script e fogli di stile. 

Nel tuo framework web, puoi mettere in cache intere risposte di route o parti costose. All'interno della tua app FastHTML, metti in cache risposte di route intere o componenti costosi, garantendo che le richieste ripetute tornino rapidamente senza ri-interrogare il database o rigenerare template.

In Python, puoi implementare il caching a livello di funzione utilizzando decorator. Ad esempio, il decorator incorporato functools.lru_cache può memorizzare i risultati di una funzione helper che recupera i dati utente. Per esempio, potresti usare questo decorator per mettere in cache le chiamate al database:

from functools import lru_cache

@lru_cache(maxsize=64)
def fetch_user_profile(user_id):
    # simulate an expensive database call
    return db.get_user(user_id)

@app.get("/profile/{user_id}")
def profile(user_id: int):
    profile = fetch_user_profile(user_id)
    return Div(P(profile.name), P(profile.email))

Code di task asincrone

Le applicazioni web restano reattive delegando i task che richiedono tempo fuori dal ciclo della richiesta. Invece di bloccare il server mentre generi report, invii email o elabori dati, questi task vengono accodati ed eseguiti in background. 

Con questo approccio, la tua applicazione invia una risposta immediata all'utente mentre worker, in processi o thread separati, elaborano i task in coda in modo asincrono.

FastHTML supporta l'esecuzione di task in background integrandosi con il BackgroundTasks di Starlette. Ecco un esempio che mostra come inviare un'email di benvenuto dopo la registrazione dell'utente.

from fasthtml.common import FastHTML, serve, Div, Form, Input, Button
from starlette.background import BackgroundTasks

app = FastHTML()

def send_welcome_email(email: str):
    # expensive or time consuming work
    ...

@app.post("/signup")
def signup(background_tasks: BackgroundTasks, request):
    form = await request.form()
    email = form["email"]
    # schedule the email task
    background_tasks.add_task(send_welcome_email, email)
    return Div("Thanks for signing up! You will receive an email shortly.")

Applicazioni reali

FastHTML è un framework versatile che può alimentare un'ampia gamma di applicazioni web. Vediamo come potresti affrontare la costruzione di una piattaforma e-commerce e di una dashboard dati usando FastHTML.

Blueprint per una piattaforma e-commerce

Costruiamo una piattaforma ecommerce con FastHTML. Inizia modellando i tuoi dati principali come classi ORM o dataclass Python: prodotti, utenti e articoli del carrello. 

Crea una pagina di elenco prodotti che iteri sui record. Per ogni prodotto, usa un componente Python riutilizzabile, come una Card, per mostrare prodotto, immagine, nome, prezzo e un pulsante "Aggiungi al carrello". Questo pulsante include attributi HTMX come hx_post e hx_target, che gli permettono di inviare una richiesta per aggiungere l'articolo al carrello in sessione dell'utente senza ricaricare l'intera pagina.

Il carrello è memorizzato nel dizionario di session dell'utente sul server. Nell'intestazione del sito, includi un componente riepilogo del carrello che si aggiorna dinamicamente con HTMX ogni volta che gli articoli vengono aggiunti o rimossi. 

La pagina del carrello legge i dati di sessione per renderizzare ciascun articolo insieme al totale complessivo. Offre anche un form di checkout collegato a una classe Python per la validazione. Quando l'utente invia il form, l'app crea un record d'ordine e svuota il carrello in sessione.

Implementazione di una dashboard dati

Una dashboard dati in FastHTML combina componenti Python con le tue sorgenti dati, usando HTMX per interattività e aggiornamenti in tempo reale. La tua logica backend (ad es. funzioni helper async, utility CRUD con cache o query ORM) recupera i dati necessari. 

Da lì, progetti una pagina con widget riutilizzabili. Questi possono includere controlli di filtro (come menu a discesa, selettori di date o caselle di ricerca) per affinare le query, card KPI per mostrare metriche chiave, tabelle dati per elencare record o grafici incorporati per visualizzare trend e confronti. 

Ogni widget è scritto come codice Python nativo, tipicamente un Div, Table o un componente Card personalizzato. FastHTML trasforma automaticamente questi oggetti in HTML al momento della risposta.

HTMX rende le dashboard interattive. Ad esempio, i widget di filtro possono usare hx_get e hx_post per richiedere dati filtrati al server, aggiornando dinamicamente tabelle o grafici senza richiedere un reload completo della pagina. 

Analisi comparativa con i framework tradizionali

FastHTML si distingue da framework tradizionali come Django e Flask semplificando sia lo sviluppo sia le prestazioni. Vediamo come si confronta su fattori chiave come tempi di setup, efficienza del codice e benchmark prestazionali.

Velocità di sviluppo

FastHTML ha due vantaggi chiave rispetto a framework come Django e Flask: tempi di setup ed efficienza del codice.

Tempo di setup

L'approccio "batteries-included" di Django richiede diversi passaggi prima di poter servire la prima pagina: installare il pacchetto, eseguire django-admin startproject, configurare le impostazioni e definire un'app. Questo spesso comporta più file e molto boilerplate prima di scrivere logica reale.

Flask è più snello. Dopo il pip install, puoi scrivere un paio di route in un singolo file. Tuttavia, devi comunque configurare i template Jinja, le cartelle static e aggiungere JavaScript per l'interattività.

Con FastHTML, il setup è minimo.

  1. Esegui pip install python-fasthtml uvicorn.
  2. Definisci route e componenti HTML pythonici. Puoi farlo in un solo file.
  3. Chiama serve().

Non serve un motore di template separato né la configurazione di una cartella static. Puoi iniziare a costruire subito.

Efficienza del codice

Con Django, anche una semplice pagina "Hello, world" richiede più file: views.py, urls.py, settings.py, templates/hello.html, oltre all'impalcatura di ORM e admin.

Flask semplifica il processo a un singolo file, ma devi comunque scrivere manualmente HTML nei template Jinja o in stringhe inline, e JavaScript per l'interattività.

FastHTML ti permette di definire la UI come oggetti Python, quindi non serve cambiare file o linguaggi. HTMX gestisce l'interattività in modo dichiarativo senza script personalizzati. Il risultato sono meno righe di codice, nessun template o pipeline di asset statici separati e un'unica superficie testabile per markup e comportamento.

Benchmark delle prestazioni

Studi di benchmark mostrano che i framework asincroni superano quelli sincroni sotto alta concorrenza. Ad esempio, in un confronto prestazionale tra Flask, Django, Quart e FastAPI, i framework asincroni (Quart e FastAPI) hanno gestito molte più richieste al secondo rispetto alle controparti sincrone. 

Ciò è attribuito ai loro meccanismi di gestione non bloccante delle richieste, che consentono di gestire più richieste simultaneamente senza attendere il completamento delle operazioni di I/O.

Tabella di confronto 

Per capire meglio come FastHTML si confronta con framework più affermati, la tabella seguente evidenzia le differenze chiave in termini di tempi di setup, efficienza del codice e caratteristiche prestazionali tra FastHTML, Flask e Django.

Feature

FastHTML

Flask

Django

Setup Time

Minimo: pip install, definisci route e componenti in un file, chiama serve()

Moderato: avvio rapido con un singolo file, ma richiede template Jinja e setup della cartella static

Lungo: richiede scaffolding del progetto, configurazione delle impostazioni, definizione delle app e più file

Template Engine

Non necessario—usa oggetti Python per l'HTML

Richiesto il motore di templating Jinja2 per le view

Usa i Template di Django con un linguaggio e una directory separati

Front-End Interactivity

Dichiarativa tramite HTMX, non serve JavaScript

JavaScript manuale tipicamente necessario per l'interattività

Richiede JavaScript per l'interattività, spesso con tool esterni

Code Efficiency

Alta: poco boilerplate, HTML pythonico, logica + UI unificate

Moderata: routing conciso ma l'HTML vive nei template, l'interattività necessita JS personalizzato

Bassa: logica, template e configurazione sono distribuiti in molti file

Performance (Concurrency)

Alta: basato su ASGI con supporto async, adatto ad alta concorrenza

Inferiore: basato su WSGI, gestione sincrona salvo estensioni async

Inferiore: basato su WSGI e sincrono di default; richiede setup aggiuntivo per il supporto async

Linee di codice per "Hello, World"

Pochissime righe in un file

Poche righe, ma richiede template o HTML inline

Più file tra view, URL, template e impostazioni

Conclusione

FastHTML offre un approccio nuovo e pythonico alla costruzione di applicazioni web, combinando la flessibilità degli oggetti Python con la potenza dell'esecuzione asincrona. Eliminando la necessità di file template separati, pipeline di asset statici e framework frontend, FastHTML snellisce lo sviluppo e ti permette di creare interfacce dinamiche e interattive in modo rapido ed efficiente.

Con HTMX per l'interattività, ASGI per le prestazioni e un'integrazione fluida con ORM compatibili con async, FastHTML è adatto a progetti web moderni—da piattaforme e-commerce a dashboard dati e oltre. Il setup minimo, il boilerplate ridotto e la codebase unificata lo rendono una scelta interessante per chi cerca un'alternativa leggera e produttiva ai framework tradizionali come Django e Flask.

Per chi è interessato a esplorare strumenti e approcci correlati allo sviluppo web in Python, le seguenti risorse offrono i prossimi passi consigliati.

Python FastHTML FAQ

In cosa FastHTML differisce da Django o Flask?

FastHTML elimina la necessità di file template separati, configurazioni di asset statici e framework frontend. Si concentra su uno sviluppo solo in Python con HTMX per l'interattività.

Posso usare FastHTML per applicazioni su larga scala?

Sì. L'architettura di FastHTML (Python + HTMX + ASGI) scala bene per applicazioni moderne e ad alte prestazioni. Per progetti grandi, puoi modularizzare la codebase con componenti riutilizzabili.

FastHTML supporta interattività dinamica come AJAX?

Sì. FastHTML usa HTMX per gestire l'interattività in modo dichiarativo, abilitando aggiornamenti parziali della pagina (simili ad AJAX) senza JavaScript personalizzato.

Posso distribuire applicazioni FastHTML nel cloud?

Assolutamente. Le app FastHTML possono essere distribuite su qualsiasi piattaforma che supporti ASGI e Python, inclusi servizi come Vercel, Fly.io e DigitalOcean.

Mark Pedigo

Autore

Mark Pedigo

Mark Pedigo, PhD, è un affermato data scientist con competenze in data science per la sanità, programmazione e didattica. Con un dottorato in Matematica, una laurea in Informatica e un Professional Certificate in AI, Mark unisce conoscenze tecniche e problem solving pratico. La sua carriera comprende ruoli nella rilevazione delle frodi, nella previsione della mortalità infantile e nella previsione finanziaria, oltre a contributi al software di stima dei costi della NASA. Come docente, ha insegnato su DataCamp e alla Washington University di St. Louis e ha fatto da mentore a programmatori junior. Nel tempo libero, Mark si gode la natura del Minnesota con la moglie Mandy e il cane Harley e suona il pianoforte jazz.

Argomenti

Correlato