Come Utilizzare Web Forms in una Applicazione Flask

L’autore ha selezionato il Fondo per Software Libero e Open Source per ricevere una donazione nell’ambito del programma Scrivi per Donazioni.

Introduzione

I moduli web, come i campi di testo e le aree di testo, consentono agli utenti di inviare dati alla tua applicazione per utilizzarli per eseguire un’azione o per inviare aree di testo più grandi all’applicazione. Ad esempio, in un’applicazione di social media, potresti fornire agli utenti una casella in cui possono aggiungere nuovo contenuto alle loro pagine. Un altro esempio è una pagina di login, dove forniresti all’utente un campo di testo per inserire il proprio nome utente e un campo password per inserire la propria password. Il server (la tua applicazione Flask in questo caso) utilizza i dati inviati dall’utente e li utilizza per effettuare l’accesso se i dati sono validi, o risponde con un messaggio come Credenziali non valide! per informare l’utente che i dati che ha inviato non sono corretti.

Flask è un framework web leggero per Python che fornisce strumenti e funzionalità utili per creare applicazioni web nel linguaggio Python. In questo tutorial, costruirai una piccola applicazione web che dimostra come utilizzare i form web. L’applicazione avrà una pagina per visualizzare messaggi che sono memorizzati in una lista Python e una pagina per aggiungere nuovi messaggi. Utilizzerai anche message flashing per informare gli utenti di un errore quando inviano dati non validi.

Prerequisiti

Passo 1 — Visualizzazione dei Messaggi

In questo passo, creerai un’applicazione Flask con una pagina index per visualizzare messaggi memorizzati in una lista di dizionari Python.

Per prima cosa, apri un nuovo file chiamato app.py per la modifica:

  1. nano app.py

Aggiungi il seguente codice all’interno del file app.py per creare un server Flask con una singola route:

flask_app/app.py
from flask import Flask, render_template

app = Flask(__name__)

messages = [{'title': 'Message One',
             'content': 'Message One Content'},
            {'title': 'Message Two',
             'content': 'Message Two Content'}
            ]

@app.route('/')
def index():
    return render_template('index.html', messages=messages)

Salva e chiudi il file.

In questo file, importi prima la classe Flask e la funzione render_template() dal pacchetto flask. Poi utilizzi la classe Flask per creare una nuova istanza di applicazione chiamata app, passando la variabile speciale __name__, necessaria affinché Flask imposti alcuni percorsi dietro le quinte. La renderizzazione dei template è trattata nel tutorial Come Usare i Template in un’Applicazione Flask.

Poi crei una lista Python globale chiamata messages, che contiene dizionari Python. Ogni dizionario ha due chiavi: title per il titolo del messaggio e content per il contenuto del messaggio. Questo è un esempio semplificato di un metodo di archiviazione dei dati; in uno scenario reale, useresti un database che salva permanentemente i dati e ti permette di manipolarli in modo più efficiente.

Dopo aver creato la lista Python, utilizzi il decoratore @app.route() per creare una funzione vista chiamata index(). In essa, restituisci una chiamata alla funzione render_template(), che indica a Flask che la route deve visualizzare un modello HTML. Dai il nome index.html a questo modello (lo creerai in seguito) e passi una variabile chiamata messages ad esso. Questa variabile contiene la lista messages che hai dichiarato in precedenza come valore e la rende disponibile al modello HTML. Le funzioni vista sono trattate nel tutorial Come Creare la Tua Prima Applicazione Web Utilizzando Flask e Python 3.

Successivamente, crea una cartella templates nella directory flask_app dove Flask cerca i modelli, quindi apri un file modello chiamato base.html, che conterrà il codice che altri modelli erediteranno per evitare la ripetizione del codice:

  1. mkdir templates
  2. nano templates/base.html

Aggiungi il seguente codice all’interno del file base.html per creare il modello base con una navbar e un blocco di contenuto:

flask_app/templates/base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %} - FlaskApp</title>
    <style>
        .message {
            padding: 10px;
            margin: 5px;
            background-color: #f3f3f3
        }
        nav a {
            color: #d64161;
            font-size: 3em;
            margin-left: 50px;
            text-decoration: none;
        }

    </style>
</head>
<body>
    <nav>
        <a href="{{ url_for('index') }}">FlaskApp</a>
        <a href="#">About</a>
    </nav>
    <hr>
    <div class="content">
        {% block content %} {% endblock %}
    </div>
</body>
</html>

Salva e chiudi il file.

Questo modello base contiene tutto il codice boilerplate HTML di cui avrai bisogno per riutilizzarlo nei tuoi altri modelli. Il blocco title verrà sostituito per impostare un titolo per ogni pagina, e il blocco content verrà sostituito con il contenuto di ogni pagina. La barra di navigazione ha due collegamenti, uno per la pagina indice dove utilizzi la funzione helper url_for() per collegarti alla funzione di visualizzazione index(), e l’altro per una pagina About se scegli di includerne una nella tua applicazione.

Successivamente, apri un modello chiamato index.html. Questo è il modello a cui hai fatto riferimento nel file app.py:

  1. nano templates/index.html

Aggiungi il seguente codice:

flask_app/templates/index.html
{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Messages {% endblock %}</h1>
    {% for message in messages %}
        <div class='message'>
            <h3>{{ message['title'] }}</h3>
            <p>{{ message['content'] }}</p>
        </div>
    {% endfor %}
{% endblock %}

Salva e chiudi il file.

In questo codice, estendi il modello base.html e sostituisci il contenuto del blocco content. Utilizzi un’intestazione <h1> che funge anche da titolo.

Utilizzi un ciclo for di Jinja nella riga {% for message in messages %} per scorrere ogni messaggio nella lista messages. Utilizzi un tag <div> per contenere il titolo e il contenuto del messaggio. Visualizzi il titolo in un’intestazione <h3> e il contenuto in un tag <p>.

Mentre sei nella directory flask_app con l’ambiente virtuale attivato, indica a Flask l’applicazione (app.py in questo caso) utilizzando la variabile d’ambiente FLASK_APP:

  1. export FLASK_APP=app

Quindi, imposta la variabile d’ambiente FLASK_ENV su development per eseguire l’applicazione in modalità sviluppo e accedere al debugger. Per ulteriori informazioni sul debugger Flask, consulta Come Gestire Gli Errori in un’Applicazione Flask. Utilizza i seguenti comandi per fare ciò (su Windows, usa set invece di export):

  1. export FLASK_ENV=development

Successivamente, esegui l’applicazione:

  1. flask run

Con il server di sviluppo in esecuzione, visita il seguente URL utilizzando il tuo browser:

http://127.0.0.1:5000/

Vedrai i messaggi nella lista messages visualizzati sulla pagina index:

Ora che hai configurato la tua applicazione web e visualizzato i messaggi, avrai bisogno di un modo per consentire agli utenti di aggiungere nuovi messaggi alla pagina index. Questo viene fatto attraverso i moduli web, che configurerai nel prossimo passaggio.

Passaggio 2 — Configurazione Dei Moduli

In questo passaggio, creerai una pagina nella tua applicazione che permette agli utenti di aggiungere nuovi messaggi alla lista dei messaggi tramite un modulo web.

Lascia il server di sviluppo in esecuzione e apri una nuova finestra del terminale.

Per prima cosa, apri il tuo file app.py:

  1. nano app.py

Aggiungi la seguente route alla fine del file:

flask_app/app.py
# ...

@app.route('/create/', methods=('GET', 'POST'))
def create():
    return render_template('create.html')

Salva e chiudi il file.

Questa rotta /create ha il parametro methods con la tupla ('GET', 'POST') per accettare sia richieste GET che POST. GET e POST sono metodi HTTP. Di default, sono accettate solo richieste GET, utilizzate per recuperare dati, come chiedere al server una pagina indice o una pagina About. Le richieste POST sono utilizzate per inviare dati a una rotta specifica, che spesso modifica i dati sul server.

In questo esempio, richiederai la pagina create utilizzando una richiesta GET. La pagina Create avrà un modulo web con campi di input e un pulsante Submit. Quando un utente compila il modulo web e clicca sul pulsante Submit, una richiesta POST viene inviata alla rotta /create. Lì gestisci la richiesta, validi i dati inviati per assicurarti che l’utente non abbia inviato un modulo vuoto, e li aggiungi alla lista messages.

La funzione di visualizzazione create() attualmente fa una sola cosa: renderizza un template chiamato create.html quando riceve una richiesta GET normale. Ora creerai questo template, quindi modificherai la funzione per gestire le richieste POST nel passo successivo.

Apri un nuovo file di template chiamato create.html:

  1. nano templates/create.html

Aggiungi il seguente codice:

flask_app/templates/create.html
{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Add a New Message {% endblock %}</h1>
    <form method="post">
        <label for="title">Title</label>
        <br>
        <input type="text" name="title"
               placeholder="Message title"
               value="{{ request.form['title'] }}"></input>
        <br>

        <label for="content">Message Content</label>
        <br>
        <textarea name="content"
                  placeholder="Message content"
                  rows="15"
                  cols="60"
                  >{{ request.form['content'] }}</textarea>
        <br>
        <button type="submit">Submit</button>
    </form>
{% endblock %}

Salva e chiudi il file.

In questo codice, estendi il modello base.html e sostituisci il blocco content con un’intestazione <h1> che funge da titolo per la pagina. Nel tag <form>, imposti l’attributo method su post in modo che i dati del modulo vengano inviati al server come richiesta POST.

Nel modulo, hai un campo di input di testo chiamato title; questo è il nome che utilizzerai nell’applicazione per accedere ai dati del modulo del titolo. Dai al tag <input> un valore di {{ request.form['title'] }}. Questo è utile per ripristinare i dati inseriti dall’utente in modo che non vadano persi quando qualcosa va storto. Ad esempio, se l’utente dimentica di compilare l’area di testo content richiesta, una richiesta viene inviata al server e un messaggio di errore verrà restituito come risposta, ma i dati nel titolo non andranno persi perché saranno salvati nell’oggetto globale request e possono essere accessibili tramite request.form['title'].

Dopo il campo di input del titolo, aggiungi un’area di testo chiamata content con il valore {{ request.form['content'] }} per gli stessi motivi menzionati in precedenza.

Infine, hai un pulsante Submit alla fine del modulo.

Ora, con il server di sviluppo in esecuzione, utilizza il tuo browser per navigare alla route /create:

http://127.0.0.1:5000/create

Vedrai una pagina “Aggiungi un Nuovo Messaggio” con un campo di input per il titolo del messaggio, un’area di testo per il contenuto del messaggio e un pulsante Submit.

Questo modulo invia una richiesta POST alla tua funzione di visualizzazione create(). Tuttavia, non c’è ancora codice per gestire una richiesta POST nella funzione, quindi non succede nulla dopo aver compilato il modulo e averlo inviato. Nel passaggio successivo, gestirai la richiesta POST in arrivo quando viene inviato un modulo. Controllerai se i dati inviati sono validi (non vuoti) e aggiungerai il titolo e il contenuto del messaggio alla lista messages.

Passaggio 3 — Gestione delle Richieste del Modulo

In questo passaggio, gestirai le richieste del modulo lato applicazione. Accederai ai dati del modulo che l’utente invia tramite il modulo creato nel passaggio precedente e li aggiungerai alla lista dei messaggi. Utilizzerai anche messaggistica flash per informare gli utenti quando inviano dati non validi. Il messaggio flash verrà mostrato una sola volta e scomparirà alla richiesta successiva (se navighi su un’altra pagina, ad esempio).

Apri il file app.py per la modifica:

  1. nano app.py

Per prima cosa, importa quanto segue dal framework Flask:

  • L’oggetto globale request per accedere ai dati della richiesta in arrivo che verranno inviati tramite il modulo HTML costruito nel passaggio precedente.
  • La funzione url_for() per generare URL.
  • La funzione flash() per inviare un messaggio quando una richiesta viene elaborata (per informare l’utente che tutto è andato bene, o per informarli di un problema se i dati inviati non sono validi).
  • La funzione redirect() per reindirizzare il client a una posizione diversa.

Aggiungi questi importi alla prima riga del file:

flask_app/app.py
from flask import Flask, render_template, request, url_for, flash, redirect

# ...

La funzione flash() memorizza i messaggi flash nella sessione del browser del client, che richiede l’impostazione di una chiave segreta. Questa chiave segreta viene utilizzata per proteggere le sessioni, che consentono a Flask di ricordare informazioni da una richiesta all’altra, come passare dalla pagina del nuovo messaggio alla pagina dell’indice. L’utente può accedere alle informazioni memorizzate nella sessione, ma non può modificarle a meno che non abbia la chiave segreta, quindi non devi mai permettere a nessuno di accedere alla tua chiave segreta. Vedi la documentazione di Flask per le sessioni per ulteriori informazioni.

La chiave segreta dovrebbe essere una lunga stringa casuale. Puoi generare una chiave segreta utilizzando il modulo os con il metodo os.urandom(), che restituisce una stringa di byte casuali adatta per uso crittografico. Per ottenere una stringa casuale utilizzandola, apri un nuovo terminale e apri la shell interattiva di Python utilizzando il seguente comando:

  1. python

Nella shell interattiva di Python, importa il modulo os dalla libreria standard e chiama il metodo os.urandom() come segue:

  1. import os
  2. os.urandom(24).hex()

Otterrai una stringa simile alla seguente:

Output
'df0331cefc6c2b9a5d0208a726a5d1c0fd37324feba25506'

Puoi utilizzare la stringa ottenuta come tua chiave segreta.

Per impostare la chiave segreta, aggiungi una configurazione SECRET_KEY alla tua applicazione tramite l’oggetto app.config. Aggiungila direttamente seguendo la definizione di app prima di definire la variabile messages:

flask_app/app.py

# ...
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your secret key'


messages = [{'title': 'Message One',
             'content': 'Message One Content'},
            {'title': 'Message Two',
             'content': 'Message Two Content'}
            ]
# ...

Successivamente, modifica la funzione di vista create() in modo che appaia esattamente come segue:

flask_app/app.py
# ...

@app.route('/create/', methods=('GET', 'POST'))
def create():
    if request.method == 'POST':
        title = request.form['title']
        content = request.form['content']

        if not title:
            flash('Title is required!')
        elif not content:
            flash('Content is required!')
        else:
            messages.append({'title': title, 'content': content})
            return redirect(url_for('index'))

    return render_template('create.html')

Nell’istruzione if assicurati che il codice che segue venga eseguito solo quando la richiesta è una richiesta POST tramite il confronto request.method == 'POST'.

Quindi estrai il titolo e il contenuto inviati dall’oggetto request.form che ti dà accesso ai dati del modulo nella richiesta. Se il titolo non è fornito, la condizione if not title sarebbe soddisfatta. In tal caso, visualizzi un messaggio all’utente informandolo che il titolo è obbligatorio utilizzando la funzione flash(). Questo aggiunge il messaggio a una lista di messaggi flash. Successivamente visualizzerai questi messaggi nella pagina come parte del template base.html. Allo stesso modo, se il contenuto non è fornito, la condizione elif not content sarà soddisfatta. In tal caso, aggiungi il messaggio 'Content is required!' alla lista dei messaggi flash.

Se il titolo e il contenuto del messaggio sono inviati correttamente, utilizzi la riga messages.append({'title': title, 'content': content}) per aggiungere un nuovo dizionario alla lista messages, con il titolo e il contenuto forniti dall’utente. Poi utilizzi la funzione redirect() per reindirizzare gli utenti alla pagina index. Utilizzi la funzione url_for() per collegarti alla pagina index.

Salva e chiudi il file.

Ora, naviga verso la route /create utilizzando il tuo browser web:

http://127.0.0.1:5000/create

Compila il modulo con un titolo a tua scelta e del contenuto. Una volta inviato il modulo, vedrai il nuovo messaggio elencato nella pagina index.

Infine, visualizzerai i messaggi flash e aggiungerai un link per la pagina “Nuovo Messaggio” alla barra di navigazione nel template base.html per avere un facile accesso a questa nuova pagina. Apri il file del template base:

  1. nano templates/base.html

Modifica il file aggiungendo un nuovo tag `` dopo il link FlaskApp nella barra di navigazione all’interno del tag `

flask_app/templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %} - FlaskApp</title>
    <style>
        .message {
            padding: 10px;
            margin: 5px;
            background-color: #f3f3f3
        }
        nav a {
            color: #d64161;
            font-size: 3em;
            margin-left: 50px;
            text-decoration: none;
        }

        .alert {
            padding: 20px;
            margin: 5px;
            color: #970020;
            background-color: #ffd5de;
        }

    </style>
</head>
<body>
    <nav>
        <a href="{{ url_for('index') }}">FlaskApp</a>
        <a href="{{ url_for('create') }}">Create</a>
        <a href="#">About</a>
    </nav>
    <hr>
    <div class="content">
        {% for message in get_flashed_messages() %}
            <div class="alert">{{ message }}</div>
        {% endfor %}
        {% block content %} {% endblock %}
    </div>
</body>
</html>

Salva e chiudi il file, quindi ricarica `https://127.0.0.1:5000` nel tuo browser. La barra di navigazione avrà ora un elemento “Create” che punta alla route `/create`.

Per vedere come funzionano i messaggi flash, vai alla pagina “Create” e clicca il pulsante Submit senza compilare i due campi. Riceverai un messaggio che assomiglia a questo:

Torna alla pagina index e vedrai che i messaggi flash sotto la barra di navigazione scompaiono, anche se sono visualizzati come parte del template base. Se non fossero messaggi flash, sarebbero visualizzati anche sulla pagina index, poiché anch’essa eredita dal template base.

Prova a inviare il modulo con un titolo ma senza contenuto. Vedrai il messaggio “Content is required!”. Clicca sul link FlaskApp nella barra di navigazione per tornare alla pagina index, poi clicca il pulsante Indietro per tornare alla pagina Crea. Vedrai che il messaggio di contenuto è ancora lì. Questo funziona solo se clicchi il pulsante Indietro, perché salva la precedente richiesta. Cliccando sul link Crea nella barra di navigazione invierai una nuova richiesta, che pulisce il modulo, e di conseguenza, il messaggio flash scomparirà.

Ora sai come ricevere l’input dell’utente, come validarlo e come aggiungerlo a una fonte di dati.

Nota:
I messaggi che aggiungi alla lista messages scompariranno ogni volta che il server viene arrestato, perché le liste Python sono salvate solo in memoria, per salvare i tuoi messaggi in modo permanente, dovrai utilizzare un database come SQLite. Dai un’occhiata a How To Use the sqlite3 Module in Python 3 per imparare come usare SQLite con Python.

Conclusione

Hai creato un’applicazione Flask dove gli utenti possono aggiungere messaggi a una lista di messaggi visualizzati sulla pagina index. Hai creato un modulo web, gestito i dati che l’utente invia tramite il modulo e li hai aggiunti alla tua lista di messaggi. Hai anche utilizzato i messaggi flash per informare l’utente quando invia dati non validi.

Se desideri saperne di più su Flask, dai un’occhiata a gli altri tutorial della serie Flask.

Source:
https://www.digitalocean.com/community/tutorials/how-to-use-web-forms-in-a-flask-application