Flask contact form project

Breve panoramica di come sto strutturando l'applicazione ContactForm realizzata con Python e Flask.

Come preannunciato nel post di ieri, sto procedendo allo sviluppo della mia mini-applicazione dedicata alla raccolta di messaggi tramite contact form. Di seguito alcuni dettagli che mi fa comodo lasciare scritti da qualche parte.

Requisiti

Quelli che seguono sono i pacchetti installati nel virtual environment specifico dell’applicazione:

alembic==1.13.1
blinker==1.8.1
click==8.1.7
dnspython==2.6.1
email_validator==2.1.1
Flask==3.0.3
Flask-Migrate==4.0.7
Flask-SQLAlchemy==3.1.1
Flask-WTF==1.2.1
greenlet==3.0.3
idna==3.7
itsdangerous==2.2.0
Jinja2==3.1.3
Mako==1.3.3
MarkupSafe==2.1.5
python-dotenv==1.0.1
setuptools==69.5.1
SQLAlchemy==2.0.29
typing_extensions==4.11.0
Werkzeug==3.0.2
wheel==0.43.0
WTForms==3.1.2

Ovviamente si tratta di quello che serve per realizzare un’applicazione Flask che faccia uso di form web e di un database per memorizzare dati (in questo caso SQLite).

Inizializzazione del database

Usando SQLAlchemy come ORM e Alembic come gestore delle migrazioni (tramite il package Flask-Migrate), possiamo usare dei tool da riga di comando per inizializzare il database e per creare ed applicare le migrazioni man mano che eseguiamo delle modifiche ai nostri model.

Il comando per inizializzare il database è il seguente:

flask db init

Affinché funzioni, si assume che venga eseguito dopo aver attivato il virtualenv e aver impostato l’applicazione Flask mediante le variabili contenute nel file .flaskenv, processato grazie al package python-dotenv.

Il risultato del comando sarà la creazione della directory migrations contenente gli script necessari a gestire le migrazioni del database.

Creare ed applicare una migrazione

Al momento il nostro database è vuoto, in quanto non abbiamo ancora creato nessuna tabella. Le tabelle vengono utilizzate per memorizzare dati che rappresentano gli oggetti definiti nei model dell’applicazione. Nel mio caso, al momento, c’è soltanto un model definito nel modo seguente:

import sqlalchemy as sa
import sqlalchemy.orm as so
from app import db


class Message(db.Model):
    id: so.Mapped[int] = so.mapped_column(primary_key=True)
    email: so.Mapped[str] = so.mapped_column(sa.String(120), index=True, unique=False)
    message: so.Mapped[str] = so.mapped_column(sa.Text, index=False, unique=False)
    verified: so.Mapped[bool] = so.mapped_column(sa.Boolean, default=False)

    def __repr__(self):
        return f'Messaggio di {self.email}: \n{self.message}'
Code language: Python (python)

La definizione ricalca in buona sostanza quella di un model illustrato nel Flask Mega-Tutorial di Miguel Grinberg, riadattato alle mie esigenze.

Per creare la migrazione che definirà (o aggiornerà) la tabella message del database, si usa il comando seguente:

flask db migrate -m "Descrizione della migrazione"Code language: JavaScript (javascript)

Il risultato è uno script Python con le funzioni di upgrade() e downgrade() da applicare al database, a seconda che si voglia applicare le modifiche oppure eseguire un rollback.

Per applicare la migrazione, ovvero eseguire la funzione upgrade() sul database, si usa il comando seguente:

flask db upgrade

Analogamente, per eseguire il rollback dell’ultima migrazione applicata, il comando da usare è:

flask db downgrade

Se, infine, si vuole azzerare completamente il database e riapplicare successivamente tutte le migrazioni, la sequenza di comandi da eseguire è la seguente:

flask db downgrade base
flask db upgrade

A che punto sono arrivato?

Ieri sera ero abbastanza pessimista circa la riuscita di questo esperimento, e avevo ragione. A poco più di due ore dalla deadline che mi sono dato, per ora ho realizzato una banale home page con un messaggio di benvenuto e la contact page che ospita la form per l’inserimento dei messaggi da parte degli utenti.

Compilando la form, se questa è valida, il messaggio viene memorizzato in un database SQLite insieme a nome ed email del mittente.

Cosa manca ancora?

Queste sono le funzioni non ancora implementate:

  • CAPTCHA, per evitare l’inserimento indiscriminato di messaggi
  • invio del messaggio inserito via email all’amministratore del sito
  • sistema di validazione dell’indirizzo email del mittente
  • applicazione di uno stile responsivo

Aggiornamenti

  • Ore 16:20 – implementata la verifica con CAPTCHA, usando il package flask-session-captcha. Abbastanza semplice, ma devo verificare se è meglio utilizzare flask-simple-captcha.
  • Ore 17:52 – implementato l’invio del messaggio via email usando l’estensione Flask-Mail (documentazione). A quanto pare, però, questo package non viene più aggiornato da una decina di anni… sarà il caso di trovare un’alternativa?
Contact form con campo captcha.
Esempio di contact form con CAPTCHA generato con flask-session-captcha.

Ultimo aggiornamento: 2 Maggio 2024 (Gica78R)