Reallizzare una webapp con Python e bottle | Expense Tracker

Reallizzare una webapp con Python e bottle | Expense Tracker

In questo esercizio vedremo come realizzare una webapp con Python e bottle. La webapp che andremo a realizzare sarà un semplice gestionale per le spese. L’utente potrà inserire le spese e visualizzare un report con le spese inserite.

Requisiti

Per realizzare la webapp utilizzeremo il linguaggio di programmazione Python e il framework bottle. Inoltre utilizzeremo il database SQLite per memorizzare i dati.

Analisi

L’applicazione che andremo a realizzare sarà un semplice gestionale per le spese. L’utente potrà inserire le spese e visualizzare un report con le spese inserite. Ogni spesa avrà una descrizione, un importo e una data. L’utente potrà inserire, modificare e cancellare le spese. Ogni spesa potrà appartenere ad una categoria (stringa) e a più tag (stringa). L’utente potrà visualizzare le spese per categoria e per tag.

Progettazione

Diagramma ER e Diagramma Concettuale

Diagramma ER

SQL e creazione del database

Ecco il codice SQL per creare il database e popolarlo con i dati di esempio.

--- 1. Create expenses table
CREATE TABLE expenses (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    description TEXT NOT NULL,
    amount REAL NOT NULL,
    date TEXT NOT NULL,
    category TEXT NOT NULL
);

--- 2. Create categories table
CREATE TABLE categories (
    name TEXT PRIMARY KEY
);

--- 3. create tags table
CREATE TABLE tags (
    name TEXT PRIMARY KEY
);

--- 4. create expenses_tags table
CREATE TABLE expenses_tags (
    expense_id INTEGER NOT NULL,
    tag_name TEXT NOT NULL,
    PRIMARY KEY (expense_id, tag_name),
    FOREIGN KEY (expense_id) REFERENCES expenses(id),
    FOREIGN KEY (tag_name) REFERENCES tags(name)
);

-- Path: db_populate.sql

--- 1. Populate categories table
INSERT INTO categories (name) VALUES ('Food');
INSERT INTO categories (name) VALUES ('Transportation');
INSERT INTO categories (name) VALUES ('Entertainment');
INSERT INTO categories (name) VALUES ('Clothing');
INSERT INTO categories (name) VALUES ('Rent');
INSERT INTO categories (name) VALUES ('Health');
INSERT INTO categories (name) VALUES ('Other');

--- 2. Populate tags table
INSERT INTO tags (name) VALUES ('lunch');
INSERT INTO tags (name) VALUES ('dinner');
INSERT INTO tags (name) VALUES ('snacks');
INSERT INTO tags (name) VALUES ('coffee');

--- 3. Populate expenses table
INSERT INTO expenses (description, amount, date, category) VALUES ('Lunch at McDonalds', 5.99, '2019-01-01', 'Food');
INSERT INTO expenses (description, amount, date, category) VALUES ('Dinner at Burger King', 7.99, '2019-01-01', 'Food');
INSERT INTO expenses (description, amount, date, category) VALUES ('Snacks at 7-11', 2.99, '2019-01-01', 'Food');
INSERT INTO expenses (description, amount, date, category) VALUES ('Coffee at Starbucks', 3.99, '2019-01-01', 'Food');
INSERT INTO expenses (description, amount, date, category) VALUES ('Lunch at McDonalds', 5.99, '2019-01-02', 'Food');
INSERT INTO expenses (description, amount, date, category) VALUES ('Dinner at Burger King', 7.99, '2019-01-02', 'Food');
INSERT INTO expenses (description, amount, date, category) VALUES ('Snacks at 7-11', 2.99, '2019-01-02', 'Food');
INSERT INTO expenses (description, amount, date, category) VALUES ('Coffee at Starbucks', 3.99, '2019-01-02', 'Food');

--- 4. Populate expenses_tags table
INSERT INTO expenses_tags (expense_id, tag_name) VALUES (1, 'lunch');
INSERT INTO expenses_tags (expense_id, tag_name) VALUES (2, 'dinner');
INSERT INTO expenses_tags (expense_id, tag_name) VALUES (3, 'snacks');
INSERT INTO expenses_tags (expense_id, tag_name) VALUES (4, 'coffee');
INSERT INTO expenses_tags (expense_id, tag_name) VALUES (5, 'lunch');

Per installare bottlepy è sufficiente scaricare il file bottle.py e salvarlo nella stessa cartella del file python che andremo a creare.

Per creare il database SQLite è sufficiente salvare il codice SQL in un file con estensione .sql e poi eseguirlo con il comando sqlite3 expensetracker.db < db_populate.sql. In alternativa, salvato il file db_populate.sql è possibile richiamarlo dal seguente file python:

import os,os.path
import sqlite3

DB_NAME = "expensetracker.db"


# load the DDL data from the file db_init.sql
db_ddl_data= ""
with open("db_init.sql", "r") as f:
    db_ddl_data = f.read()
    

if os.path.exists(DB_NAME):
    os.remove(DB_NAME)


con = sqlite3.connect(DB_NAME)

with con:
    cur = con.cursor()
    cur.executescript(db_ddl_data)

Ecco il codice dell’applicazione.

Codice Python

from bottle import route, run, template,view, static_file,request,post, redirect,get

import sqlite3

DB_NAME = "expensetracker.db"
con = sqlite3.connect(DB_NAME)

def expense_tuple_to_dict(expense_tuple):
    return {"id":expense_tuple[0],"description":expense_tuple[1],"amount":expense_tuple[2],"date":expense_tuple[3],"category":expense_tuple[4]}

@get('/expenses')
@view('hello_template')
def hello():
    cursor = con.execute("SELECT * FROM expenses")
    expenses = []
    for row in cursor:
        print(expense_tuple_to_dict(row))
        expenses.append(expense_tuple_to_dict(row))
 
    return {"name":"Ciao a tutti",'expenses':expenses}




@post("/expenses")
def create_expense():
    if request.forms.get('_method') == 'delete':
        return delete_expense(request.forms.get('id'))
    
    data = {
        "date": request.forms.get('date'),
       "description" : request.forms.get('description'),
        "amount": request.forms.get('amount'),
        "category": request.forms.get('category')
    }
    print(request.forms)
    cursor = con.execute("INSERT INTO expenses (date,description,amount,category) VALUES (?,?,?,?)",
                         (data["date"],data["description"],data["amount"],data["category"]))
    con.commit()
    return redirect("/expenses")

def delete_expense(id):
    cursor = con.execute("DELETE FROM expenses WHERE id = ?",(id,))
    con.commit()
    return redirect("/expenses")

@route('/static/<filename:path>')
def send_static(filename):
    return static_file(filename, root='static/')

run(host='localhost', port=8080, debug=True)

Descrizione del codice

  • DB_NAME = "expensetracker.db": Questa riga definisce una variabile DB_NAME che contiene il nome del file del database SQLite in cui saranno memorizzate le informazioni sulle spese. Il file del database sarà chiamato “expensetracker.db”.

  • con = sqlite3.connect(DB_NAME): Qui viene stabilita una connessione al database SQLite specificato nella variabile DB_NAME utilizzando il modulo sqlite3. La connessione è memorizzata nella variabile con e verrà utilizzata per eseguire query sul database.

  • def expense_tuple_to_dict(expense_tuple): Questa è una funzione definita dall’utente chiamata expense_tuple_to_dict. Prende in input una tupla expense_tuple e restituisce un dizionario che rappresenta una singola spesa. I campi del dizionario includono “id”, “description”, “amount”, “date” e “category”, che corrispondono ai valori nella tupla.

  • @route('/hello'): Questo è un decorator che associa la funzione hello() alla route ‘/hello’. In altre parole, quando l’applicazione web riceve una richiesta HTTP per la route ‘/hello’, verrà eseguita la funzione hello().

  • @view('hello_template'): Questo è un altro decorator che specifica il nome del modello da utilizzare per generare la risposta HTML. In questo caso, il modello chiamato ‘hello_template’ verrà utilizzato per generare la pagina HTML.

  • def hello(): Questa è la funzione principale che verrà eseguita quando si accede alla route ‘/hello’. All’interno di questa funzione:

    a. Si esegue una query SQL sul database per selezionare tutte le righe dalla tabella “expenses”.

    b. Viene inizializzata una lista vuota chiamata expenses.

    c. Per ogni riga risultante dalla query, viene chiamata la funzione expense_tuple_to_dict() per convertire la tupla in un dizionario rappresentante una spesa. Il dizionario risultante viene quindi aggiunto alla lista expenses.

    d. Infine, viene restituito un dizionario che contiene una chiave “name” con il valore “Ciao a tutti” e una chiave “expenses” con il valore della lista expenses.

  • run(host='localhost', port=8080, debug=True): Questo comando avvia il server web locale sulla porta 8080 e abilita la modalità di debug. Ciò significa che l’applicazione sarà accessibile all’indirizzo "http://localhost:8080" e verrà mostrato l’output di debug in caso di errori o eccezioni.

Templates

hello_template.tpl

% rebase('base.tpl',title='test')

<form action="/expenses" method="post">
    Description: <input name="description" type="text" />
    Amount: <input name="amount" type="number" min=0 step=0.01 />
    Date: <input name="date" type="date" />
    <input value="Create" type="submit" />
    <select name="category">
        <option value="food">Food</option>
        <option value="transport">Transport</option>
        <option value="housing">Housing</option>
        <option value="utilities">Utilities</option>
        <option value="clothing">Clothing</option>
        <option value="health">Health</option>
        <option value="insurance">Insurance</option>
        <option value="household">Household</option>
        <option value="personal">Personal</option>
        <option value="education">Education</option>
        <option value="entertainment">Entertainment</option>
        <option value="gifts">Gifts</option>
        <option value="other">Other</option>
    </select>
</form>

<table class="table-auto">
  <thead>
    <tr>
     <th>Date</th>
      <th>Description</th>
      <th>Amount</th>
      <th>Category</th>
      <th>Actions</th>
    </tr>
  </thead>
  <tbody>
  %for expense in expenses:
    <tr>
    <td>{{expense['date']}}</td>
      <td>{{expense['description']}}</td>
      <td>{{expense['amount']}}</td>
      <td>{{expense['category']}}</td>
      <td>
        <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
          Edit
        </button>
        <form action="/expenses" method="post"> 
        <input type="hidden" name="id" value="{{expense['id']}}" />
        <input type="hidden" name="_method" value="delete" />
        <button class="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">
          Delete
        </button>
        </form>
     
        </td>
    </tr>
   %end
  </tbody>
</table>

%if name == 'World':
    <h1 class="text-3xl font-bold underline">Hello {{name}}!</h1>
    <p>This is a test.</p>
%else:
    <h1 class="text-3xl font-bold underline">Hello {{name}}!</h1>
    <p>How are you?</p>
%end

%for expense in expenses:
    <p>You spent {{expense}} {{expense['category']}}</p>
%end

base.tpl

<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="/static/main.css" rel="stylesheet">
</head>
<body>
  <h1 class="text-3xl font-bold underline">
    {{title}}
  </h1>
  <div  class="container mx-auto">
  {{!base}}
  </div>
</body>
</html>

Related Posts

descriptive text

7 Esercizi sui diagrammi concettuali

La progettazione concettuale dei database è una fase importante nello sviluppo di un database. In questa fase, si identificano i dati necessari per rappresentare la realtà di interesse e si modella

Leggi
descriptive text

Aspetto intensionale ed estensionale dei dati

## L'aspetto estensionale dei datiL'aspetto estensionale dei dati si riferisce al contenuto dei dati, cioè all'insieme di valori che i dati possono assumere. È il contenuto dei dati che viene effett

Leggi
descriptive text

Definzione di Database e di SQL

## Cos'è un database?Un database è una raccolta strutturata di dati elettronici. Questi dati possono essere consultati, gestiti, modificati, aggiornati, controllati e organizzati con l'aiuto di un

Leggi
descriptive text

Dati e Informazioni

# Dati e informazioni: la differenza fondamentaleIn informatica, i dati e le informazioni sono due concetti fondamentali che sono spesso confusi tra loro. In realtà, si tratta di due cose molto d

Leggi
descriptive text

Definzione di DBMS

Un sistema di gestione delle basi di dati, noto anche come database management system (DBMS), rappresenta il software che funge da intermediario tra gli utenti finali, le applicazioni e la banca dati

Leggi
descriptive text

Definizione di base di dati

Una base di dati, spesso abbreviata come "DB" o "database", è una raccolta di dati strutturati, organizzati in modo da consentire l'archiviazione, la gestione, la ricerca, l'aggiornamento e la manipo

Leggi
descriptive text

Diagramma concettuale di un social tipo Instagram | Esercizio sui diagrammi concettuali

Un'azienda desidera creare un social network tipo Instagram. Gli utenti possono registrarsi sulla piattaforma e fornire informazioni personali come nome, cognome, indirizzo email e password. Aggiun

Leggi
descriptive text

Diagramma concettuale di un social tipo Twitter | Esercizio sui diagrammi concettuali

Un'azienda desidera creare un social network tipo Twitter. Gli utenti possono registrarsi sulla piattaforma e fornire informazioni personali come nome, cognome, indirizzo email e password. Aggiunger

Leggi
descriptive text

Esercizio database gestione spese | Esercizi SQL

Creare un database che consenta di gestire una base dati relativa alle spese personali. Ogni spesa appartiene ad una categoria e ogni spesa può appartenere a più tags. Dopo aver fatto una adeguata

Leggi
descriptive text

Gestione file come google drive | Esercizio sui diagrammi concettuali

Un'azienda desidera creare un sistema di gestione per i suoi file. I dipendenti possono caricare file, visualizzare dettagli sui file e scaricare quelli di loro interesse. Ogni dipendente deve regi

Leggi
descriptive text

libreria online | Esercizio sui diagrammi concettuali

Una libreria online desidera creare un sistema di gestione per i suoi libri e i suoi clienti. I clienti possono cercare libri, visualizzare dettagli sui libri e acquistare quelli di loro interesse.

Leggi
descriptive text

Gestione Ecommerce | Esercizio sui diagrammi concettuali

Un'azienda di e-commerce desidera creare un sistema di gestione per i suoi prodotti e i suoi clienti. I clienti possono cercare prodotti, visualizzare dettagli sui prodotti e acquistarli quelli di

Leggi
descriptive text

Gestione museo | Esercizio sui diagrammi concettuali

Si vuole rappresentare una base dati per la gestione di un museo, tenendo conto delle seguenti informazioni:- I musei sono identificati da un codice univoco. Per ciascun museo sono noti il nome,

Leggi
descriptive text

Gestione noleggio auto | Esercizio sui diagrammi concettuali

Una società di noleggio auto intende gestire un sistema online per consentire ai clienti di prenotare veicoli per un periodo specifico. I clienti devono registrarsi come utenti sulla piattaforma e

Leggi
descriptive text

Gestione noleggio biciclette | Esercizio sui diagrammi concettuali

Si vuole rappresentare una base dati per la gestione di un servizio di noleggio di biciclette, tenendo conto delle seguenti informazioni:- I clienti del servizio sono identificati da un codice

Leggi
descriptive text

Gestione ordini pizzeria | Esercizio sui diagrammi concettuali

Viene chiesto di realizzare il sistema informatico della pizzeria "Bella Zi". Le esigenze del committente sono quelle di gestire i clienti salvando l'anagrafica e gestire gli ordini effettuati che

Leggi
descriptive text

Maturità Informatica Ordinaria 2004 | Diagramma concettuale e logico

[Tema di esame](https://www.istruzione.it/esame_di_stato/Secondo_Ciclo/tracce_prove_scritte/2005/tecnica/M070.pdf)## Soluzione![Maturità ordinaria 2004|Diagramma concettuale](/images/maturita-

Leggi
descriptive text

Simulazione Esame Informatica | Logistica aziendale

Una società di logistica sta sviluppando un sistema informatico per gestire il flusso delle merci all'interno della propria rete aziendale. La società gestisce una vasta gamma di merci e ha una rete

Leggi
descriptive text

Simulazione Esame Informatica | Gestione azienda sviluppo software

Una società di sviluppo software sta pianificando l'implementazione di un sistema informatico per gestire in modo efficiente il ciclo di sviluppo del software e le risorse umane coinvolte. Questa soc

Leggi
descriptive text

Progettazione un Database: modello concettuale e logico

La progettazione di un database è un processo complesso che richiede una profonda conoscenza

Leggi
descriptive text

Tipi di basi di dati

Esistono diversi tipi di basi di dati, a seconda della loro struttura, della tecnologia utilizzata e del modello di dati utilizzato.I principali tipi di basi di dati sono:- **Basi di dati relazio

Leggi
descriptive text

L'ascesa del C: dalla sua nascita al trono della programmazione

Il linguaggio di programmazione C è uno dei pilastri fondamentali dell'informatica moderna. La sua ascesa verso il trono della programmazione è stata un viaggio affascinante, caratterizzato da innova

Leggi
descriptive text

Il Pattern DAO (Data Access Object) in Java

Il pattern DAO (Data Access Object) è un pattern architetturale che viene spesso utilizzato nelle applicazioni Java per separare la logica di accesso ai dati dal resto dell'applicazione. In questo mo

Leggi