ReportLab: Creare PDF con Python

Ritorniamo un po’ a parlare di quello che più ci piace fare di più: sviluppare software! 
Tempo fa ero alla ricerca di un ottimo metodo che mi permettesse di stampare etichette per un processo industriale. La scelta ricadde su Python per una serie di motivi particolari legati al sistema in uso su le macchine presenti in loco. Ora il dilemma era scegliere la libreria migliore per generare dei PDF da inviare alle macchine di stampa. Scriverne una nuova sarebbe stata un’enorme perdita di tempo e visto che, fortunatamente, viviamo in un mondo costellato di ottimi progetti Open Source, dove è possibile trovare sempre quello che fa al caso proprio, mi sono messo alla ricerca di qualcosa che mi aiutasse in questa problematica. Nelle ricerche effettuate mi sono imbattuto in numerosi progetti interessanti ma uno in particolare pare essere completo ed altamente funzionante: la libreria pdfgen di reportlab. Esistono due versione della stessa libreria, quella base e quella plus. Per i nostri scopi quella più semplice va benissimo ed è anche quella che troveremo nei nostri repository.
Per iniziare ad utilizzare pdfgen dobbiamo prima installare il necessario. Basterà recarsi nel proprio gestore di pacchetti ed installare python-reportlab o digitare nel terminale (per sistemi debian.based):

# apt-get install python-reportlab

A questo punto possiamo includere la libreria nei nostri sorgenti python con:
import reportlab.pdfgen
Analizziamo ora un semplice script per vedere il funzionamento di questo strumento:
—– Python —–
#!/usr/bin/env python

from reportlab.pdfgen import canvas (1)
from datetime import datetime

mio_pdf = canvas.Canvas(‘mio.pdf’) (2)
# —– imposta le dimensioni a 7.2 x 2.3 cm
mio_pdf.setPageSize((204.0944882400, 65.1968504100)) (3)

# —– scrive la data di oggi nel pdf
mio_pdf.drawString(0,54,str(datetime.today())) (4)
# —– genera e salva il pdf
mio_pdf.showPage() (5)
mio_pdfp.save() (6)
———-
Come si vede il codice è molto semplice ma molto potente. Analizziamolo passo per passo anche se i commenti dovrebbero essere di per sè molto chiari. Partendo dal primo rigo di codice utile, si importa semplicemente la funzione canvas dalla libreria (1). Tale funzione è quella che si occupa di “disegnare” il documento ed il suo contenuto. Sarà la funzione che più utilizzerete nel vostro codice e perciò vi conviene studiarla per bene. Successivamente (2) viene generato il contenitore per i nostri dati e si definiscono le dimensioni in punti (3). Al suo interno poi si definiscono le coordinate in stile cartesiano (a partire dal punto in basso a sinistra che rappresenta lo 0,0) in cui inserire il nostro contenuto. Qui (4) si è scelto di stampare la data di oggi in un punto indicativamente in alto a sinistra. Infine (5) si genera il PDF con tutto ciò che è stato creato e lo si salva (6) nella path in cui viene eseguito il nostro script.
La libreria è molto potente e permette di definire numerosissimi valori per generare al meglio il nostro documento secondo le nostre esigenze. Per la documentazione completa vi rimando al sito ufficiale che risulta essere completo ed esaustivo nella maggior parte dei casi. 
Per ogni dubbio non esitate ad utilizzare i commenti. Cercherò di aiutarvi.

Portare avanti o indietro una data in python

Quando si opera nel campo dei software gestionali, si ha sempre la necessità di lavorare con le date e le loro mille sfaccettature. Gestire una data non è sempre cosa facile poiché essa può essere formattata in modi diversi e la necessità del momento può spingerci a doverla nuovamente riformattare secondo un canone decisamente diverso (se non opposto) rispetto all’originale.

In questo articolo vedremo come, grazie all’ausilio delle librerie del linguaggio, è possibile, con poche righe di codice, “muovere” una data nel passato o nel futuro partendo da una a nostra disposizione.

Immaginiamo di dove gestire la scadenza di un servizio. All’utente verrà chiesto (nel modo che si richiede più opportuno) di fornire una data di avvio del servizio e la sua durata. Nel nostro caso l’utente dovrà specificare quest’ultimo parametro in giorni. Riversiamo i dati così ottenuti rispettivamente nelle variabili data_avvio e durata_giorni e calcoliamo la data di chiusura del servizio.

—python—————-
from datetime import date, datetime, time, timedelta
def calcola_scadenza(data_attivazione, durata_giorni):
        str_data_attivazione = datetime.strptime(data_attivazione,’%Y-%m-%d’)
        data_fine = data_attivazione + timedelta(days=durata_giorni)
        res = datetime.strftime(data_fine,’%Y-%m-%d’)
        return res
——————————

Innanzitutto partiamo con l’importazione del necessario dalla libreria datetime. Questa libreria è molto versatile ed utilissima quando si vuole lavorare con questo particolare tipo di dati. Inoltre è ben documentata ed è semplice da usare nei propri progetti. Ora definiamo la nostra funzione che accetta come parametri la data di avvio e la durata in giorni del servizio. Successivamente, mediante l’ausilio della funzione datetime.strptime si converte la stringa in un formato data che rispetta la formattazione definita come secondo parametro. Nel nostro caso la data avrà formato anno-mese-giorno. Qui arriva la parte interessante dell’algoritmo. Come si può vedere la data di fine servizio viene calcolata grazie all’uso di timedelta. Come il nome della funzione lascia intendere, timedelta serve a creare una data con un offset calcolato in base ai parametri passati alla stessa. In questo caso abbiamo deciso di spostare la data attuale di n giorni nel fututo dicendo a timedelta di spostarsi in base ai giorni (days). Infine con datetime.strftime compiamo l’operazione inversa rispetto a datetime.strptime, ovvero otteniamo una stringa partendo da una data e lasciamo la funzione ritornando il valore appena ottenuto.

Nonostante l’esempio sia volutamente ridotto al minimo indispensabile, è possibile notare con facilità come gli strumenti mostrati siano potenti e versatili semplificando non di poco il lavoro dello sviluppatore. Timedelta, ad esempio, ci permette di tornare indietro passando i parametri in forma negativa. Questo può essere notevolmente utile quando si vuole sapere la data di qualche giorno o mese fa. Importante è anche l’uso di datetime. Grazie a strftime e strptime è possibile ottenere date formattate come meglio si crede. Ora non resta che sperimentare quanto imparato.
      

Django: Creare fields readonly

Il progetto Django ha come scopo la creazione di un framework, rivolto al web, mediante il quale è possibile creare in maniera facile e veloce siti o portali web dinamici usando la comoda sintassi del Python e gli strumenti messi a disposizione dal progetto stesso. 
Lo sviluppo di siti web in Django prevede l’adesione dello stesso agli standard della programmazione MTV (Model-Template-View). Per maggiori informazioni vi invito ad effettuare delle ricerche nel web.
Grazie a Django è possibile creare dei form da inserire nelle proprie pagine web per poter eseguire comuni operazioni a cui si è già abituati: impostazione di filtri sui dati, invio di email, iscrizione ad un servizio, etc. I vari campi che costituiscono il form vengono chiamati fields. Può essere necessario, a volte, dover visualizzare un field in modalità di sola lettura ad esempio per poter mostrare agli utenti un dato senza permetterne la modifica. 
Immaginiamo di dover crear un form per l’invio delle email che mostri all’utente l’indirizzo di posta elettronica del webmaster a cui verrà inviata la segnalazione. Il seguente articolo mostrerà semplicemente il sistema di gestione dei widget. Ogni altra operazione verrà considerata come già nota all’utente che legge il seguente articolo.

Rechiamoci nel file views.py dell’applicazione del nostro progetto. Spostiamoci alla fine dello stesso ed inseriamo il seguente codice:

class mail_form(forms.Form):
     webmaster-mail = forms.CharField(widget = forms.TextInput(attrs={‘readonly’:’readonly’}))
     user_mail = forms.EmailField()
     user_name = forms.CharField()
     mail_content = forms.CharField()



Come si può vedere il campo webmaster_mail è impostato, mediante la proprietà widget, in modalità di sola lettura. 
Nell’immagine che segue è possibile vedere la differenza tra un CharField tradizione ed uno in sola lettura.
Questo sistema ovviamente può essere utilizzato su ogni tipo di field così da permetterne la visualizzazione e non la modifica.