Come utilizzare Flask-SQLAlchemy per interagire con database in un’applicazione Flask

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

Introduzione

Nelle applicazioni web, di solito è necessario un database, che è una raccolta organizzata di dati. Si utilizza un database per memorizzare e mantenere dati persistenti che possono essere recuperati e manipolati in modo efficiente. Ad esempio, in un’applicazione di social media, si ha un database in cui i dati degli utenti (informazioni personali, post, commenti, follower) sono memorizzati in modo che possano essere manipolati in modo efficiente. Si possono aggiungere dati a un database, recuperarli, modificarli o eliminarli, a seconda di diversi requisiti e condizioni. In un’applicazione web, questi requisiti potrebbero essere un utente che aggiunge un nuovo post, elimina un post o cancella il proprio account, il che potrebbe o meno comportare l’eliminazione dei loro post. Le azioni che si compiono per manipolare i dati dipenderanno dalle specifiche funzionalità della propria applicazione. Ad esempio, potrebbe non voler consentire agli utenti di aggiungere post senza titolo.

Effettua il deploy delle tue applicazioni Flask da GitHub usando la Piattaforma App di DigitalOcean. Lascia che DigitalOcean si concentri sullo scaling della tua app.

Flask è un framework web Python leggero che offre strumenti e funzionalità utili per creare applicazioni web in linguaggio Python. SQLAlchemy è uno strumento SQL che fornisce un accesso efficiente e ad alte prestazioni alle basi di dati relazionali. Offre modi per interagire con diversi motori di database come SQLite, MySQL e PostgreSQL. Ti dà accesso alle funzionalità SQL del database. Ti fornisce anche un Object Relational Mapper (ORM), che ti permette di fare query e gestire dati utilizzando semplici oggetti e metodi Python. Flask-SQLAlchemy è un’estensione di Flask che facilita l’uso di SQLAlchemy con Flask, fornendoti strumenti e metodi per interagire con il tuo database nelle tue applicazioni Flask tramite SQLAlchemy.

In questo tutorial, costruirai un piccolo sistema di gestione studenti che dimostra come utilizzare l’estensione Flask-SQLAlchemy. Lo userai con Flask per eseguire compiti di base, come connettersi a un server di database, creare una tabella, aggiungere dati alla tua tabella, recuperarli e aggiornare ed eliminare elementi dal tuo database. Userai SQLAlchemy con SQLite, anche se puoi usarlo con altri motori di database, come PostgreSQL e MySQL. SQLite funziona bene con Python perché la libreria standard di Python fornisce il sqlite3 modulo, che viene utilizzato da SQLAlchemy dietro le quinte per interagire con i database SQLite senza dover installare nulla. SQlite è installato sui sistemi Linux di default, ed è installato come parte del pacchetto Python su Windows.

Prerequisiti

Passaggio 1 — Installazione di Flask e Flask-SQLAlchemy

In questo passaggio, installerai i pacchetti necessari per la tua applicazione.

Con il tuo ambiente virtuale attivato, utilizza pip per installare Flask e Flask-SQLAlchemy:

  1. pip install Flask Flask-SQLAlchemy

Una volta completata l’installazione con successo, vedrai una riga simile alla seguente alla fine dell’output:

Output
Successfully installed Flask-2.0.3 Flask-SQLAlchemy-2.5.1 Jinja2-3.0.3 MarkupSafe-2.1.0 SQLAlchemy-1.4.31 Werkzeug-2.0.3 click-8.0.4 greenlet-1.1.2 itsdangerous-2.1.0

Con i pacchetti Python richiesti installati, configurerai il database successivamente.

Passaggio 2 — Configurazione del Database e del Modello

In questo passaggio, imposterai la connessione al database e creerai un modello di database SQLAlchemy, che è una classe Python che rappresenta la tabella che memorizza i tuoi dati. Inizierai il database, creerai una tabella per gli studenti basata sul modello che dichiarerai, e aggiungerai alcuni studenti nella tua tabella degli studenti.

Configurazione della connessione al database

Apri un file chiamato app.py nella tua directory flask_app. Questo file conterrà il codice per impostare il database e le tue route Flask:

  1. nano app.py

Questo file si collegherà a un database SQLite chiamato database.db, e avrà una classe chiamata Student che rappresenta la tabella degli studenti del database per memorizzare le informazioni degli studenti, oltre alle tue route Flask. Aggiungi le seguenti dichiarazioni import all’inizio di app.py:

flask_app/app.py
import os
from flask import Flask, render_template, request, url_for, redirect
from flask_sqlalchemy import SQLAlchemy

from sqlalchemy.sql import func

Qui, importi il modulo os, che ti fornisce accesso a interfacce del sistema operativo varie. Lo utilizzerai per costruire un percorso del file per il tuo file di database database.db.

Dal pacchetto flask, importi quindi gli helper necessari per la tua applicazione: la classe Flask per creare un’istanza dell’applicazione Flask, la funzione render_template() per renderizzare i modelli, l’oggetto request per gestire le richieste, la funzione url_for() per costruire URL per le route, e la funzione redirect() per reindirizzare gli utenti. Per ulteriori informazioni sulle route e sui modelli, consulta Come utilizzare i modelli in un’applicazione Flask.

Importi quindi la classe SQLAlchemy dall’estensione Flask-SQLAlchemy, che ti fornisce accesso a tutte le funzioni e classi di SQLAlchemy, oltre a helper e funzionalità che integrano Flask con SQLAlchemy. Lo utilizzerai per creare un oggetto database che si collega alla tua applicazione Flask, consentendoti di creare e manipolare tabelle utilizzando classi, oggetti e funzioni Python senza dover utilizzare il linguaggio SQL.

Importi anche l’helper func dal modulo sqlalchemy.sql per accedere alle funzioni SQL. Ne avrai bisogno nel sistema di gestione degli studenti per impostare una data e un’ora di creazione predefinite quando viene creato un record studente.

Sotto gli import, configurerai un percorso del file del database, istanzierai la tua applicazione Flask e configurerai e collegherai la tua applicazione con SQLAlchemy. Aggiungi il seguente codice:

flask_app/app.py

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] =\
        'sqlite:///' + os.path.join(basedir, 'database.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

Qui, si costruisce un percorso per il file del database SQLite. Prima si definisce una directory di base come la directory corrente. Si utilizza la funzione os.path.abspath() per ottenere il percorso assoluto della directory del file corrente. La variabile speciale __file__ contiene il percorso del file app.py corrente. Si memorizza il percorso assoluto della directory di base in una variabile chiamata basedir.

Si crea quindi un’istanza dell’applicazione Flask chiamata app, che viene utilizzata per configurare due chiavi di configurazione di Flask-SQLAlchemy :

  • SQLALCHEMY_DATABASE_URI: L’URI del database per specificare il database con cui si desidera stabilire una connessione. In questo caso, l’URI segue il formato sqlite:///percorso/al/database.db. Si utilizza la funzione os.path.join() per unire intelligentemente la directory di base che è stata costruita e memorizzata nella variabile basedir, e il nome del file database.db. Questo si collegherà a un file di database database.db nella directory flask_app. Il file verrà creato una volta iniziato il database.

  • SQLALCHEMY_TRACK_MODIFICATIONS: Una configurazione per abilitare o disabilitare il tracciamento delle modifiche degli oggetti. Lo imposti su Falso per disabilitare il tracciamento e utilizzare meno memoria. Per ulteriori informazioni, consulta la pagina di configurazione nella documentazione di Flask-SQLAlchemy.

Nota:

Se desideri utilizzare un altro motore di database come PostgreSQL o MySQL, dovrai utilizzare l’URI corretto.

Per PostgreSQL, utilizza il seguente formato:

postgresql://username:password@host:port/database_name

Per MySQL:

mysql://username:password@host:port/database_name

Per ulteriori informazioni, consultare la documentazione di SQLAlchemy per la configurazione del motore.

Dopo aver configurato SQLAlchemy impostando un URI del database e disabilitando il tracciamento, si crea un oggetto database utilizzando la classe SQLAlchemy, passando l’istanza dell’applicazione per connettere la tua applicazione Flask con SQLAlchemy. Si memorizza l’oggetto database in una variabile chiamata db. Utilizzerai questo oggetto db per interagire con il tuo database.

Dichiarare la Tabella

Con la connessione al database stabilita e l’oggetto database creato, utilizzerai l’oggetto database per creare una tabella del database per gli studenti, che è rappresentata da un modello – una classe Python che eredita da una classe di base fornita da Flask-SQLAlchemy tramite l’istanza del database db che hai creato in precedenza. Per definire una tabella studenti come modello, aggiungi la seguente classe al tuo file app.py:

flask_app/app.py
# ...

class Student(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    firstname = db.Column(db.String(100), nullable=False)
    lastname = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(80), unique=True, nullable=False)
    age = db.Column(db.Integer)
    created_at = db.Column(db.DateTime(timezone=True),
                           server_default=func.now())
    bio = db.Column(db.Text)

    def __repr__(self):
        return f'<Student {self.firstname}>'

Qui, si crea un modello Student, che eredita dalla classe db.Model. Questo rappresenta la tabella degli studenti. Si utilizza la classe db.Column per definire le colonne della tua tabella. Il primo argomento rappresenta il tipo di colonna, e gli argomenti aggiuntivi rappresentano la configurazione della colonna.

Definisci le seguenti colonne per il modello Studente:

  • id: L’ID dello studente. Lo definisci come un intero con db.Integer. primary_key=True definisce questa colonna come una chiave primaria, che le assegnerà un valore univoco nel database per ogni voce (cioè uno studente).
  • nome: Il nome dello studente. Una stringa con una lunghezza massima di 100 caratteri. nullable=False significa che questa colonna non deve essere vuota.
  • cognome: Il cognome dello studente. Una stringa con una lunghezza massima di 100 caratteri. nullable=False significa che questa colonna non deve essere vuota.
  • email: L’email dello studente. Una stringa con una lunghezza massima di 80 caratteri. unique=True significa che ogni email dovrebbe essere unica per ogni studente. nullable=False significa che questa colonna non deve essere vuota.
  • età: L’età dello studente.
  • created_at: L’ora in cui è stata creata la registrazione dello studente nel database. Si utilizza db.DateTime per definirla come un oggetto datetime di Python. timezone=True abilita il supporto del fuso orario. server_default imposta il valore predefinito nel database durante la creazione della tabella, in modo che i valori predefiniti siano gestiti dal database piuttosto che dal modello. Si passa ad essa la funzione func.now() che richiama la funzione datetime SQL now(). In SQLite, viene reso come CURRENT_TIMESTAMP durante la creazione della tabella degli studenti.
  • bio: La biografia dello studente. db.Text() indica che la colonna contiene testi lunghi.

Vedere la documentazione di SQLAlchemy per tipi di colonne diversi dai tipi utilizzati nel blocco di codice precedente.

La speciale funzione __repr__ consente di fornire a ciascun oggetto una rappresentazione stringa per riconoscerlo a scopo di debug. In questo caso si utilizza il nome dello studente.

Il file app.py avrà ora il seguente aspetto:

flask_app/app.py
import os
from flask import Flask, render_template, request, url_for, redirect
from flask_sqlalchemy import SQLAlchemy

from sqlalchemy.sql import func


basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] =\
        'sqlite:///' + os.path.join(basedir, 'database.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)


class Student(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    firstname = db.Column(db.String(100), nullable=False)
    lastname = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(80), unique=True, nullable=False)
    age = db.Column(db.Integer)
    created_at = db.Column(db.DateTime(timezone=True),
                           server_default=func.now())
    bio = db.Column(db.Text)

    def __repr__(self):
        return f'<Student {self.firstname}>'

Salva e chiudi app.py.

Creazione del Database

Ora che hai impostato la connessione al database e il modello dello studente, utilizzerai la shell di Flask per creare il tuo database e la tua tabella degli studenti basata sul modello Studente.

Con il tuo ambiente virtuale attivato, imposta il file app.py come tua applicazione Flask utilizzando la variabile di ambiente FLASK_APP. Quindi apri la shell di Flask usando il seguente comando nella tua directory flask_app:

  1. export FLASK_APP=app
  2. flask shell

A Python interactive shell will be opened. This special shell runs commands in the context of your Flask application, so that the Flask-SQLAlchemy functions you’ll call are connected to your application.

Importa l’oggetto del database e il modello dello studente, e poi esegui la funzione db.create_all() per creare le tabelle associate ai tuoi modelli. In questo caso hai solo un modello, il che significa che la chiamata di funzione creerà solo una tabella nel tuo database:

  1. from app import db, Student
  2. db.create_all()

Lascia la shell in esecuzione, apri un’altra finestra del terminale e naviga nella tua directory flask_app. Ora vedrai un nuovo file chiamato database.db in flask_app.

Nota:

La funzione db.create_all() non ricrea o aggiorna una tabella se esiste già. Ad esempio, se modifichi il tuo modello aggiungendo una nuova colonna e esegui la funzione db.create_all(), la modifica apportata al modello non verrà applicata alla tabella se la tabella esiste già nel database. La soluzione è eliminare tutte le tabelle del database esistenti con la funzione db.drop_all() e quindi ricrearle con la funzione db.create_all() in questo modo:

  1. db.drop_all()
  2. db.create_all()

Questo applicherà le modifiche apportate ai tuoi modelli, ma eliminerà anche tutti i dati esistenti nel database. Per aggiornare il database e preservare i dati esistenti, dovrai utilizzare la migrazione dello schema, che ti consente di modificare le tabelle e preservare i dati. Puoi utilizzare l’estensione Flask-Migrate per eseguire le migrazioni dello schema di SQLAlchemy tramite l’interfaccia della riga di comando di Flask.

Se ricevi un errore, assicurati che l’URI del database e la dichiarazione del modello siano corretti.

Popolamento della Tabella

Dopo aver creato il database e la tabella degli studenti, utilizzerai la shell di Flask per aggiungere alcuni studenti al tuo database attraverso il modello Student.

Utilizza la stessa shell di Flask che hai aperto in precedenza, o aprine una nuova con il tuo ambiente virtuale attivato nella directory flask_app.

  1. flask shell

Per aggiungere uno studente al tuo database, importerai l’oggetto database e il modello Student, e creerai un’istanza del modello Student, passandogli i dati dello studente tramite argomenti di parola chiave come segue:

  1. from app import db, Student
  2. student_john = Student(firstname='john', lastname='doe',
  3. email='[email protected]', age=23,
  4. bio='Biology student')

L’oggetto student_john rappresenta uno studente che verrà aggiunto al database, ma questo oggetto non è ancora stato scritto nel database. Dai un’occhiata all’oggetto nella shell di Flask per vedere la stringa di rappresentazione che hai costruito con il metodo __repr__():

  1. student_john

Riceverai il seguente output:

Output
<Student john>

Puoi ottenere il valore delle colonne utilizzando gli attributi di classe che hai definito nel modello Student:

  1. student_john.firstname
  2. student_john.bio
Output
'john' 'Biology student'

Poiché questo studente non è ancora stato aggiunto al database, il suo ID sarà None:

  1. print(student_john.id)
Output
None

Per aggiungere questo studente al database, prima dovrai aggiungerlo a una sessione del database, che gestisce una transazione del database. Flask-SQLAlchemy fornisce l’oggetto db.session attraverso il quale puoi gestire le modifiche al database. Aggiungi l’oggetto student_john alla sessione utilizzando il metodo db.session.add() per prepararlo a essere scritto nel database:

  1. db.session.add(student_john)

Questo emetterà un’istruzione INSERT, ma non otterrai un ID indietro perché la transazione del database non è ancora stata eseguita. Per confermare la transazione e applicare la modifica al database, utilizza il metodo db.session.commit():

  1. db.session.commit()

Ora che lo studente John è stato aggiunto al database, puoi ottenere il suo ID:

  1. print(student_john.id)
Output
1

Puoi anche utilizzare il metodo db.session.add() per modificare un elemento nel database. Ad esempio, puoi modificare l’email dello studente in questo modo:

  1. student_john.email = '[email protected]'
  2. db.session.add(student_john)
  3. db.session.commit()

Usa il terminale di Flask per aggiungere alcuni altri studenti al tuo database:

  1. sammy = Student(firstname='Sammy',
  2. lastname='Shark',
  3. email='[email protected]',
  4. age=20,
  5. bio='Marine biology student')
  6. carl = Student(firstname='Carl',
  7. lastname='White',
  8. email='[email protected]',
  9. age=22,
  10. bio='Marine geology student')
  11. db.session.add(sammy)
  12. db.session.add(carl)
  13. db.session.commit()

Ora, puoi interrogare tutti i record nella tabella degli studenti utilizzando l’attributo query con il metodo all():

  1. Student.query.all()

Riceverai il seguente output:

Output
[<Student john>, <Student Sammy>, <Student Carl>]

In questo momento, hai tre studenti nel tuo database. Successivamente, creerai un percorso Flask per la pagina di indice e visualizzerai tutti gli studenti nel tuo database su di essa.

Passaggio 3 — Visualizzazione di Tutti i Record

In questo passaggio, creerai un percorso e un modello per visualizzare tutti gli studenti nel database sulla pagina di indice.

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

Apri il tuo file app.py per aggiungere un percorso per la pagina di indice ad esso:

  1. nano app.py

Aggiungi il seguente percorso alla fine del file:

flask_app/app.py

# ...

@app.route('/')
def index():
    students = Student.query.all()
    return render_template('index.html', students=students)

Salva e chiudi il file.

Qui, crei una funzione index() utilizzando il decoratore app.route(). In questa funzione, esegui una query al database e ottieni tutti gli studenti utilizzando il modello Student con l’attributo query, che ti consente di recuperare uno o più elementi dal database utilizzando metodi diversi. Utilizzi il metodo all() per ottenere tutte le voci degli studenti nel database. Salvi il risultato della query in una variabile chiamata students e la passi a un modello chiamato index.html che renderizzi utilizzando la funzione di assistenza render_template().

Prima di creare il file del modello index.html su cui visualizzerai gli studenti esistenti nel database, creerai prima un modello di base, che conterrà tutto il codice HTML di base che altri modelli utilizzeranno anche per evitare la ripetizione del codice. Quindi creerai il file del modello index.html che hai renderizzato nella tua funzione index(). Per saperne di più sui modelli, consulta Come utilizzare i modelli in un’applicazione Flask.

Crea una directory templates, quindi apri un nuovo modello chiamato base.html:

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

Aggiungi il seguente codice all’interno del file base.html:

flask_app/templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %} - FlaskApp</title>
    <style>
        .title {
            margin: 5px;
        }

        .content {
            margin: 5px;
            width: 100%;
            display: flex;
            flex-direction: row;
            flex-wrap: wrap;
        }

        .student {
            flex: 20%;
            padding: 10px;
            margin: 5px;
            background-color: #f3f3f3;
            inline-size: 100%;
        }

        .bio {
            padding: 10px;
            margin: 5px;
            background-color: #ffffff;
            color: #004835;
        }

        .name a {
            color: #00a36f;
            text-decoration: none;
        }

        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="#">Create</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 boilerplate HTML di cui avrai bisogno per riutilizzarlo nei tuoi altri modelli. Il blocco title sarà sostituito per impostare un titolo per ogni pagina, e il blocco content sarà sostituito con il contenuto di ogni pagina. La barra di navigazione ha tre link: uno per la pagina di indice, che collega alla funzione di visualizzazione index() utilizzando la funzione di supporto url_for(), uno per una pagina Crea, e uno per una pagina Chi siamo se scegli di aggiungerne una all’applicazione. Modificherai questo file in seguito dopo aver aggiunto una pagina per la creazione di nuovi studenti per rendere il link Crea funzionale.

Successivamente, apri un nuovo file di modello 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 class="title">{% block title %} Students {% endblock %}</h1>
    <div class="content">
        {% for student in students %}
            <div class="student">
                <p><b>#{{ student.id }}</b></p>
                <b>
                    <p class="name">{{ student.firstname }} {{ student.lastname }}</p>
                </b>
                <p>{{ student.email }}</p>
                <p>{{ student.age }} years old.</p>
                <p>Joined: {{ student.created_at }}</p>
                <div class="bio">
                    <h4>Bio</h4>
                    <p>{{ student.bio }}</p>
                </div>
            </div>
        {% endfor %}
    </div>
{% endblock %}

Salva e chiudi il file.

Qui, estendi il modello base e sostituisci i contenuti del blocco di contenuto. Utilizzi un’intestazione <h1> che funge anche da titolo. Utilizzi un loop Jinja for nella riga {% for student in students %} per passare attraverso ogni studente nella variabile students che hai passato dalla funzione di visualizzazione index() a questo modello. Visualizzi l’ID dello studente, il loro nome e cognome, email, età, la data in cui sono stati aggiunti al database e la loro biografia.

Mentre ti trovi nella directory flask_app con il tuo ambiente virtuale attivato, comunica a Flask dell’applicazione (app.py in questo caso) utilizzando la variabile d’ambiente FLASK_APP. Quindi impostare la variabile d’ambiente FLASK_ENV su development per eseguire l’applicazione in modalità di sviluppo e ottenere accesso al debugger. Per ulteriori informazioni sul debugger di Flask, consultare Come Gestire gli Errori in un’Applicazione Flask. Utilizzare i seguenti comandi per farlo:

  1. export FLASK_APP=app
  2. export FLASK_ENV=development

Successivamente, eseguire l’applicazione:

  1. flask run

Con il server di sviluppo in esecuzione, visitare l’URL seguente utilizzando il proprio browser:

http://127.0.0.1:5000/

Saranno visualizzati gli studenti che hai aggiunto al database in una pagina simile alla seguente:

Hai visualizzato gli studenti che hai nel tuo database nella pagina di indice. Successivamente, creerai un percorso per una pagina studente, dove potrai visualizzare i dettagli di ciascuno studente singolo.

Passaggio 4 — Visualizzazione di un Singolo Record

In questo passaggio, utilizzerai la shell di Flask per interrogare gli studenti per il loro ID e creare un percorso e un modello per visualizzare i dettagli di ciascuno studente su una pagina dedicata.

Alla fine di questo passaggio, l’URL http://127.0.0.1:5000/1 sarà una pagina che visualizza il primo studente (perché ha l’ID 1). L’URL http://127.0.0.1:5000/ID visualizzerà il post con il numero ID associato, se esiste.

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

Apri la shell di Flask per una dimostrazione di come interrogare gli studenti:

  1. flask shell

Per interrogare i record e recuperare dati dal database, Flask-SQLAlchemy fornisce un attributo query sulla classe del modello. Puoi usare i suoi metodi per ottenere record con un filtro specifico.

Ad esempio, puoi utilizzare il metodo filter_by() con un parametro come firstname che corrisponde a una colonna nella tabella con un argomento per recuperare uno studente specifico:

  1. from app import db, Student
  2. Student.query.filter_by(firstname='Sammy').all()
Output
[<Student Sammy>]

Qui recuperi tutti gli studenti con Sammy come loro primo nome. Usi il metodo all() per ottenere una lista di tutti i risultati. Per ottenere il primo risultato, che è l’unico risultato qui, puoi usare il metodo first():

  1. Student.query.filter_by(firstname='Sammy').first()
Output
<Student Sammy>

Per ottenere uno studente dal suo ID, puoi usare filter_by(id=ID):

  1. Student.query.filter_by(id=3).first()

In alternativa, puoi usare il metodo più breve get(), che ti consente di recuperare un elemento specifico utilizzando la sua chiave primaria:

  1. Student.query.get(3)

Entrambi daranno lo stesso output:

Output
<Student Carl>

Ora puoi uscire dalla shell:

  1. exit()

Per recuperare uno studente tramite il loro ID, creerai una nuova route che renderà una pagina per ogni singolo studente. Utilizzerai il metodo get_or_404() fornito da Flask-SQLAlchemy, che è una variante del metodo get(). La differenza è che get() restituisce il valore None quando nessun risultato corrisponde all’ID fornito, mentre get_or_404() restituisce una risposta HTTP 404 Not Found. Apri app.py per la modifica:

  1. nano app.py

Aggiungi la seguente route alla fine del file:

flask_app/app.py
# ...

@app.route('/<int:student_id>/')
def student(student_id):
    student = Student.query.get_or_404(student_id)
    return render_template('student.html', student=student)

Salva e chiudi il file.

Qui, utilizzi la route '/<int:student_id>/', con int: come un convertitore che converte la stringa predefinita nell’URL in un numero intero. E student_id è la variabile URL che determinerà lo studente che visualizzerai sulla pagina.

L’ID viene passato dall’URL alla funzione di vista student() attraverso il parametro student_id. All’interno della funzione, esegui una query sulla collezione degli studenti e recupera uno studente tramite l’ID utilizzando il metodo get_or_404(). Questo salverà i dati dello studente nella variabile student se esiste e risponderà con un errore HTTP 404 Not Found se non esiste uno studente con l’ID fornito nel database.

Rendi un template chiamato student.html e passa lo studente che hai recuperato.

Apri questo nuovo file di template student.html:

  1. nano templates/student.html

Digitare il seguente codice in questo nuovo file student.html. Questo sarà simile al template index.html, tranne che visualizzerà solo uno studente:

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

{% block content %}
    <span class="title">
        <h1>{% block title %} {{ student.firstname }} {{ student.lastname }}{% endblock %}</h1>
    </span>
    <div class="content">
            <div class="student">
                <p><b>#{{ student.id }}</b></p>
                <b>
                    <p class="name">{{ student.firstname }} {{ student.lastname }}</p>
                </b>
                <p>{{ student.email }}</p>
                <p>{{ student.age }} years old.</p>
                <p>Joined: {{ student.created_at }}</p>
                <div class="bio">
                    <h4>Bio</h4>
                    <p>{{ student.bio }}</p>
                </div>
            </div>
    </div>
{% endblock %}

Salvare e chiudere il file.

In questo file, estendi il template di base, impostando il nome completo dello studente come titolo della pagina. Visualizzi l’ID dello studente, il nome e cognome dello studente, l’email, l’età, la data di creazione del record e la loro biografia.

Utilizza il browser per navigare all’URL del secondo studente:

http://127.0.0.1:5000/2

Vedrai una pagina simile alla seguente:

Ora, modifica index.html per fare in modo che il nome di ogni studente sia un link alla loro pagina:

  1. nano templates/index.html

Modifica il ciclo for come segue:

flask_app/templates/index.html
{% for student in students %}
    <div class="student">
        <p><b>#{{ student.id }}</b></p>
        <b>
            <p class="name">
                <a href="{{ url_for('student', student_id=student.id)}}">
                    {{ student.firstname }} {{ student.lastname }}
                </a>
            </p>
        </b>
        <p>{{ student.email }}</p>
        <p>{{ student.age }} years old.</p>
        <p>Joined: {{ student.created_at }}</p>
        <div class="bio">
            <h4>Bio</h4>
            <p>{{ student.bio }}</p>
        </div>
    </div>
{% endfor %}

Salvare e chiudere il file.

Hai aggiunto un tag <a> al nome completo dello studente che collega alla pagina dello studente utilizzando la funzione url_for(), passando l’ID dello studente memorizzato in student.id alla funzione di visualizzazione student().

Naviga alla tua pagina di indice o aggiornala:

http://127.0.0.1:5000/

Ora vedrai che ogni nome dello studente collega alla pagina dello studente corretta.

Dopo aver creato una pagina per gli studenti singoli, aggiungerai successivamente una pagina per aggiungere nuovi studenti al database.

Passo 5 — Creazione di un Nuovo Record

In questo passaggio, aggiungerai una nuova route alla tua applicazione per aggiungere nuovi studenti al database utilizzando moduli web.

Renderizzerai una pagina con un modulo web in cui gli utenti inseriscono i dati dello studente. Quindi gestirai l’invio del modulo, creerai un oggetto per il nuovo studente utilizzando il modello Student, lo aggiungerai alla sessione e quindi confermerai la transazione, in modo simile a come hai aggiunto voci degli studenti nel Passaggio 2.

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

Prima, apri il tuo file app.py:

  1. nano app.py

Aggiungi la seguente route alla fine del file app.py:

flask_app/app.py
# ...


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

Salva e chiudi il file.

In questa route, passi la tupla ('GET', 'POST') al parametro methods per consentire sia le richieste GET che POST. Le richieste GET vengono utilizzate per recuperare dati dal server. Le richieste POST vengono utilizzate per inviare dati a una specifica route. Per impostazione predefinita, sono consentite solo le richieste GET. Quando l’utente richiede per la prima volta la route /create utilizzando una richiesta GET, verrà renderizzato un file di template chiamato create.html. In seguito modificherai questa route per gestire le richieste POST quando gli utenti compilano e inviano il modulo web per aggiungere nuovi studenti.

Apri il nuovo template create.html:

  1. nano templates/create.html

Aggiungi il seguente codice ad esso:

{% extends 'base.html' %}

{% block content %}
    <h1 style="width: 100%">{% block title %} Add a New Student {% endblock %}</h1>
    <form method="post">
        <p>
            <label for="firstname">First Name</label>
            <input type="text" name="firstname"
                   placeholder="First name">
            </input>
        </p>

        <p>
            <label for="lastname">Last Name</label>
            <input type="text" name="lastname"
                   placeholder="Last name">
            </input>
        </p>

        <p>
            <label for="email">Email</label>
            <input type="email" name="email"
                   placeholder="Student email">
            </input>
        </p>

        <p>
            <label for="age">Age</label>
            <input type="number" name="age"
                   placeholder="Age">
            </input>
        </p>

        <p>
        <label for="bio">Bio</label>
        <br>
        <textarea name="bio"
                  placeholder="Bio"
                  rows="15"
                  cols="60"
                  ></textarea>
        </p>
        <p>
            <button type="submit">Submit</button>
        </p>
    </form>
{% endblock %}

Salva e chiudi il file.

Estendi il modello di base, imposta un’intestazione come titolo e utilizza un tag <form> con l’attributo method impostato su post per indicare che il modulo invierà una richiesta POST.

Hai due campi di testo con i nomi firstname e lastname. Utilizzerai questi nomi per accedere ai dati del modulo che l’utente invia nella tua funzione di visualizzazione successivamente.

Hai un campo email con il nome email, un campo numerico per l’età dello studente e un’area di testo per la biografia dello studente.

Infine, hai un pulsante Invia alla fine del modulo.

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

http://127.0.0.1:5000/create

Vedrai una pagina Aggiungi un nuovo studente con un modulo web e un pulsante Invia come segue:

Se compili il modulo e lo invii, inviando una richiesta POST al server, non succede nulla perché non hai gestito le richieste POST sulla rotta /create.

Apri app.py per gestire la richiesta POST inviata dall’utente:

  1. nano app.py

Modifica la rotta /create in questo modo:

flask_app/app.py

@app.route('/create/', methods=('GET', 'POST'))
def create():
    if request.method == 'POST':
        firstname = request.form['firstname']
        lastname = request.form['lastname']
        email = request.form['email']
        age = int(request.form['age'])
        bio = request.form['bio']
        student = Student(firstname=firstname,
                          lastname=lastname,
                          email=email,
                          age=age,
                          bio=bio)
        db.session.add(student)
        db.session.commit()

        return redirect(url_for('index'))

    return render_template('create.html')

Salva e chiudi il file.

Gestisci le richieste POST all’interno della condizione if request.method == 'POST'. Estrai il nome, il cognome, l’email, l’età e la biografia che l’utente invia dall’oggetto request.form. Converti l’età passata come stringa in un intero usando la funzione Python int(). Costruisci un oggetto studente utilizzando il modello Studente. Aggiungi l’oggetto studente alla sessione del database, quindi esegui il commit della transazione.

Infine, reindirizza l’utente alla pagina di indice dove può vedere lo studente appena aggiunto sotto gli studenti esistenti.

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

http://127.0.0.1:5000/create

Compila il modulo con alcuni dati e invialo.

Sarai reindirizzato alla pagina di indice dove vedrai il tuo nuovo studente aggiunto.

Ora che hai la funzionalità per aggiungere nuovi studenti, dovrai aggiungere un collegamento alla pagina Crea nella barra di navigazione. Apri base.html:

  1. nano templates/base.html

Modifica il tag <body> modificando il valore dell’attributo href per il collegamento Crea:

flask_app/templates/base.html
<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">
        {% block content %} {% endblock %}
    </div>
</body>

Salva e chiudi il file.

Aggiorna la tua pagina di indice e noterai che il collegamento Crea nella barra di navigazione è ora funzionale.

Ora hai una pagina con un modulo web per aggiungere nuovi studenti. Per ulteriori informazioni sui moduli web, vedi Come utilizzare i moduli web in un’applicazione Flask. Per un metodo più avanzato e sicuro di gestire i moduli web, vedi Come utilizzare e convalidare i moduli web con Flask-WTF. Successivamente, aggiungerai una pagina per modificare i dati degli studenti esistenti.

Passaggio 6 — Modifica di un Record

In questo passaggio, aggiungerai una nuova pagina alla tua applicazione per modificare i dati degli studenti esistenti. Aggiungerai una nuova rotta /ID/edit/ per modificare i dati degli studenti in base al loro ID.

Apri app.py:

  1. nano app.py

Aggiungi la seguente rotta alla fine del file. Questo recupera l’entrata dello studente che desideri modificare utilizzando il suo ID. Estrae i nuovi dati dello studente inviati tramite un modulo web che creerai in seguito. Quindi modifica i dati dello studente e reindirizza l’utente alla pagina di indice:

flask_app/app.py
# ...


@app.route('/<int:student_id>/edit/', methods=('GET', 'POST'))
def edit(student_id):
    student = Student.query.get_or_404(student_id)

    if request.method == 'POST':
        firstname = request.form['firstname']
        lastname = request.form['lastname']
        email = request.form['email']
        age = int(request.form['age'])
        bio = request.form['bio']

        student.firstname = firstname
        student.lastname = lastname
        student.email = email
        student.age = age
        student.bio = bio

        db.session.add(student)
        db.session.commit()

        return redirect(url_for('index'))

    return render_template('edit.html', student=student)

Salva e chiudi il file.

Qui hai la rotta /<int:student_id>/edit/ che accetta sia i metodi POST che GET, con student_id come variabile URL che passa l’ID alla funzione di visualizzazione edit().

Usi il metodo di query get_or_404() sul modello Student per ottenere lo studente associato all’ID studente fornito. Questo risponderà con un errore 404 Not Found nel caso in cui non esista uno studente con l’ID fornito nel database.

Se l’ID fornito ha uno studente associato ad esso, l’esecuzione del codice continua alla condizione if request.method == 'POST'. Se la richiesta era una richiesta GET, il che significa che l’utente non ha inviato un modulo, allora questa condizione è falsa e il codice al suo interno verrà saltato fino alla riga return render_template('edit.html', student=student). Questo renderizza un modello edit.html, passandogli l’oggetto studente ottenuto dal database, consentendoti di compilare il modulo web dello studente con i dati dello studente correnti. Creerai questo modello edit.html successivamente.

Quando un utente modifica i dati dello studente e invia il modulo, viene eseguito il codice all’interno del if request.method == 'POST'. Estrai i dati dello studente inviati dal modulo dall’oggetto request.form in variabili corrispondenti. Imposti ciascun attributo dell’oggetto student ai dati appena inviati per cambiare i valori delle colonne come hai fatto nel Passo 2. Se nessuna modifica è stata eseguita su un campo nel modulo web, il valore di quella colonna rimarrà lo stesso nel database.

Dopo aver impostato i dati dello studente ai dati appena inviati, aggiungi l’oggetto student alla sessione del database, quindi confermi le modifiche. Infine, reindirizzi l’utente alla pagina di indice.

Successivamente, devi creare una pagina in cui gli utenti possono fare la modifica. Apri un nuovo modello edit.html:

  1. nano templates/edit.html

Questo nuovo file avrà un modulo web simile a quello presente nel file create.html con i dati degli studenti attuali come valori predefiniti per i campi. Aggiungi il seguente codice all’interno:

flask_app/templates/edit.html

{% extends 'base.html' %}

{% block content %}
    <h1 style="width: 100%">
        {% block title %} Edit {{ student.firstname }}
                               {{ student.lastname }}'s Details
        {% endblock %}
    </h1>
    <form method="post">
        <p>
            <label for="firstname">First Name</label>
            <input type="text" name="firstname"
                   value={{ student.firstname }}
                   placeholder="First name">
            </input>
        </p>

        <p>
            <label for="lastname">Last Name</label>
            <input type="text" name="lastname"
                   value={{ student.lastname }}
                   placeholder="Last name">
            </input>
        </p>

        <p>
            <label for="email">Email</label>
            <input type="email" name="email"
                   value={{ student.email }}
                   placeholder="Student email">
            </input>
        </p>

        <p>
            <label for="age">Age</label>
            <input type="number" name="age"
                   value={{ student.age }}
                   placeholder="Age">
            </input>
        </p>

        <p>
        <label for="bio">Bio</label>
        <br>
        <textarea name="bio"
                  placeholder="Bio"
                  rows="15"
                  cols="60"
                  >{{ student.bio }}</textarea>
        </p>
        <p>
            <button type="submit">Submit</button>
        </p>
    </form>
{% endblock %}

Salva e chiudi il file.

Il titolo ha il nome e cognome dello studente. L’attributo value di ogni campo di input e il valore dell’area di testo bio sono impostati sul valore corrispondente nell’oggetto student passato dalla funzione edit() alla pagina modello edit.html.

Ora, vai all’URL seguente per modificare i dettagli del primo studente:

http://127.0.0.1:5000/1/edit

Vedrai una pagina simile alla seguente:

Modifica i dati dello studente e invia il modulo. Sarai reindirizzato alla pagina principale e le informazioni dello studente saranno aggiornate.

Successivamente, aggiungerai un pulsante Edit sotto ogni studente nella pagina principale per collegarsi alla loro pagina di modifica. Apri il file del modello index.html:

  1. nano templates/index.html

Modifica il ciclo for in questo file index.html in modo che sia esattamente come segue:

flask_app/templates/index.html

{% for student in students %}
    <div class="student">
        <p><b>#{{ student.id }}</b></p>
        <b>
            <p class="name">
                <a href="{{ url_for('student', student_id=student.id)}}">
                    {{ student.firstname }} {{ student.lastname }}
                </a>
            </p>
        </b>
        <p>{{ student.email }}</p>
        <p>{{ student.age }} years old.</p>
        <p>Joined: {{ student.created_at }}</p>
        <div class="bio">
            <h4>Bio</h4>
            <p>{{ student.bio }}</p>
        </div>
        <a href="{{ url_for('edit', student_id=student.id) }}">Edit</a>
    </div>
{% endfor %}

Salva e chiudi il file.

Qui aggiungi un tag <a> per collegarsi alla funzione edit(), passando il valore student.id per collegarsi alla pagina di modifica di ciascuno studente con un collegamento Edit.

Ora hai una pagina per modificare gli studenti esistenti. Successivamente, aggiungerai un pulsante Delete per eliminare gli studenti dal database.

Passaggio 7 — Eliminazione di un Record

In questo passaggio, aggiungerai una nuova route e un pulsante Elimina per eliminare gli studenti esistenti.

Per prima cosa, aggiungerai una nuova route /id/delete che accetta richieste POST. La tua nuova funzione di visualizzazione delete() riceverà l’ID dello studente che desideri eliminare, passerà l’ID al metodo di query get_or_404() sul modello Student per ottenerlo se esiste, o risponderà con una pagina 404 Not Found se non è stato trovato alcuno studente con l’ID fornito nel database.

Apri app.py per la modifica:

  1. nano app.py

Aggiungi la seguente route alla fine del file:

flask_app/app.py

# ...

@app.post('/<int:student_id>/delete/')
def delete(student_id):
    student = Student.query.get_or_404(student_id)
    db.session.delete(student)
    db.session.commit()
    return redirect(url_for('index'))

Salva e chiudi il file.

Qui, invece di utilizzare il solito decoratore app.route, si utilizza il decoratore app.post introdotto in Flask versione 2.0.0, che ha aggiunto scorciatoie per i metodi HTTP comuni. Ad esempio, @app.post("/login") è una scorciatoia per @app.route("/login", methods=["POST"]). Ciò significa che questa funzione di vista accetta solo richieste POST, e navigare verso il percorso /ID/delete sul tuo browser restituirà un errore 405 Method Not Allowed, perché i browser web predefiniscono le richieste GET. Per eliminare uno studente, l’utente fa clic su un pulsante che invia una richiesta POST a questo percorso.

Questa funzione di vista delete() riceve l’ID dello studente da eliminare tramite la variabile URL student_id. Si utilizza il metodo get_or_404() per ottenere uno studente e salvarlo in una variabile student, o rispondere con un 404 Not Found nel caso in cui lo studente non esista. Si utilizza il metodo delete() sulla sessione del database nella riga db.session.delete(student), passandogli l’oggetto studente. Questo imposta la sessione per eliminare lo studente ogni volta che viene eseguita la transazione. Poiché non è necessario eseguire altre modifiche, si esegue direttamente la commit della transazione utilizzando db.session.commit(). Infine, si reindirizza l’utente alla pagina di indice.

Successivamente, modifica il modello index.html per aggiungere un Elimina Studente pulsante:

  1. nano templates/index.html

Modifica il for loop aggiungendo un nuovo tag <form> direttamente sotto il link Edit:

flask_app/templates/index.html

{% for student in students %}
    <div class="student">
        <p><b>#{{ student.id }}</b></p>
        <b>
            <p class="name">
                <a href="{{ url_for('student', student_id=student.id)}}">
                    {{ student.firstname }} {{ student.lastname }}
                </a>
            </p>
        </b>
        <p>{{ student.email }}</p>
        <p>{{ student.age }} years old.</p>
        <p>Joined: {{ student.created_at }}</p>
        <div class="bio">
            <h4>Bio</h4>
            <p>{{ student.bio }}</p>
        </div>
        <a href="{{ url_for('edit', student_id=student.id) }}">Edit</a>

        <hr>
        <form method="POST"
                action="{{ url_for('delete', student_id=student.id) }}">
            <input type="submit" value="Delete Student"
                onclick="return confirm('Are you sure you want to delete this entry?')">
        </form>

    </div>
{% endfor %}

Salva e chiudi il file.

Qui, hai un modulo web che invia una richiesta POST alla funzione di visualizzazione delete(). Passi student.id come argomento per il parametro student_id per specificare l’elemento studente da eliminare. Utilizzi la funzione confirm() disponibile nei browser web per mostrare un messaggio di conferma prima di inviare la richiesta.

Aggiorna ora la tua pagina di indice.

Vedrai un pulsante Delete Student sotto ogni voce dello studente. Clicca su di esso e conferma l’eliminazione. Sarai reindirizzato alla pagina di indice e lo studente non sarà più presente.

Ora hai un modo per eliminare gli studenti dal database nella tua applicazione di gestione degli studenti.

Conclusione

Hai creato una piccola applicazione web Flask per la gestione degli studenti utilizzando Flask e Flask-SQLAlchemy con un database SQLite. Hai imparato come connetterti al tuo database, configurare i modelli del database che rappresentano le tue tabelle, aggiungere elementi al tuo database, interrogare la tua tabella e modificare i dati del database.

Utilizzare SQLAlchemy nella tua applicazione ti permette di utilizzare classi e oggetti Python per gestire il tuo database SQL. Invece di SQLite, puoi utilizzare un altro motore di database, e oltre alla configurazione SQLALCHEMY_DATABASE_URI responsabile della connessione, non è necessario cambiare nulla nel codice principale dell’applicazione. Ciò ti consente di passare da un motore di database SQL a un altro con minime modifiche al codice. Consulta la documentazione di Flask-SQLAlchemy per ulteriori informazioni.

Se desideri leggere ulteriori informazioni su Flask, dai un’occhiata agli altri tutorial della serie Come Costruire Applicazioni Web con Flask.

Source:
https://www.digitalocean.com/community/tutorials/how-to-use-flask-sqlalchemy-to-interact-with-databases-in-a-flask-application