Creare siti e blog con Pelican

Da alcuni anni è possibile creare un sito ed un blog con estrema facilità e rapidità usando piattaforme come WordPress, Tumblr e Blogger. Tuttavia, mi da ancora molta soddisfazione mettere le mani al codice ed assemblare manualmente le varie componenti di un sito: solo in questo modo si ha il pieno controllo e la massima libertà su ciò che si sta creando.

Nel 1997, quando mi avvicinai alla creazione di siti web, imparai ad usare MS FrontPage per creare pagine web statiche: all’epoca, era molto “comodo” usare questo programma, perché permetteva di creare siti come se si stesse formattando un documento Word… in questo modo, FrontPage permetteva di costruire le pagine web modificando l’anteprima di ciò che sarebbe dovuto apparire nel browser.

Successivamente, passai a Macromedia Dreamweaver che offriva strumenti più potenti per l’impaginazione dei documenti, il controllo di script e fogli stile a cascata, e la creazione di template.

A partire dal 2000, abbandonai i programmi menzionati ed incominciai a creare siti web dinamici, programmando con Perl script CGI e sfruttando la tecnologia lato server SSI (Server Side Include); all’epoca, le pagine web avevano estensione “.shtm” o “.shtml” per essere processate lato server.

Fra il 2002 ed il 2006 mi sono appassionato sempre di più alla programmazione lato server con Php e MySQL, ed ho anche creato dei Content Management System per i miei siti, assecondando il modello di separare “grafica”, “contenuto” e “logica”.

Dopo il 2006, dovetti limitare fortemente il tempo da dedicare alla programmazione ed alla creazione di siti web, ma riuscii comunque a fare esperienza con Python e Django.

Recentemente, come racconto nella mia pagina di presentazione, mi sono riavvicinato allo sviluppo di siti web ed ho scoperto Pelican!

Introduzione a Pelican

Pelican é uno programma scritto in Python, che permette di generare un blog o un sito web a partire da modelli HTML/CSS (template) e contenuti scritti in semplici file di testo. In pratica, usando Pelican NON occorre usare script CGI, SSI, Php, Python e database online… è sufficiente un servizio di hosting web per semplici file statici.

Sono molto soddisfatto di usare Pelican per creare i miei siti web perché:

  1. è facile da imparare
  2. la pubblicazione è veloce ed il processo di produzione avviene offline
  3. non richiede particolari software installati sul web server
  4. il caricamento delle pagine web è velocissimo in quanto non devono essere elaborate lato server
  5. la manutenzione dei siti è facile e garantita grazie alla completa separazione di contenuti e modelli grafici
  6. la sicurezza dei siti dipende unicamente dal server HTTP prescelto ed eventuali componenti esterne che elaborano l’input degli utenti
  7. è estensibile e dispone già di molti plug-in e template
  8. la documentazione ufficiale è chiara e concisa
  9. vi sono diversi template grafici
  10. è divertente!

Creazione rapida di un sito

Pelican si installa sul computer locale e non sul server web. Nel mio caso, uso Windows 10 home, Python 3.5.2 ed ho installato i pacchetti necessari, per usare Pelican, con “pip”:

> pip install pelican markdown typogrify

dopo aver installato Pelican, potete eseguire il comando con l’opzione -h per ottenere una breve guida

> pelican -h

Per inizializzare un progetto Pelican, occorre eseguire le seguenti istruzioni:

> md yoursite
> cd yoursite
> pelican-quickstart

In questo modo, Pelican creerà le seguenti directory e files:

yoursite/
├── content/
├── output/
├── develop_server.sh
├── fabfile.py
├── Makefile
├── pelicanconf.py       # Impostazioni principali
└── publishconf.py       # Impostazioni da usare quando si pubblica online

Per iniziare, creo un file di testo con estensione “.md” nella cartella “content”.

Title: My First Review
Date: 2010-12-03 10:20
Category: Review

Following is a review of my favorite mechanical keyboard.

Salvo il file avendo cura di specificare il formato “UTF-8”, altrimenti il successivo comando di generazione del sito produrrà un errore. Dopo aver creato il contenuto, si può generare il sito e visualizzarlo con:

> pelican content
> cd output
> python -m pelican.server

In questo modo verrà eseguito il server di prova per visualizzare il sito all’indirizzo http://localhost:8000/

Gli articoli e le pagine del sito

Pelican distingue i contenuti in pagine e articoli. Le pagine sono contenuti che non fanno riferimento ad un archivio temporale e vengono usate per testi come la “presentazione del sito”, la “pagina dei contatti”, quella sul “trattamento dei dati personali”, etc… Gli articoli, sono invece contenuti strettamente collegati ad una sequenza temporale e possono essere raggruppati in categorie e tag. Entrambi i tipi di contenuti, sono creati come semplici file di testo codificati nello standard UTF-8 come nel seguente esempio:

Title: Ritorno al sito statico con Pelican
Tags: pelican
Date: 2017-05-04
Status: published
Cover: pelican-static-site.jpg
CoverAcknowledgement: Foto di [Yair Hazout](https://unsplash.com/@yairhazout){:target="_blank"}

Nel 1997, quando mi avvicinai alla creazione di siti web, imparai ad usare **MS FrontPage** per creare pagine web statiche: all'epoca, era molto "comodo" usare questo programma, perché permetteva di creare siti come se si stesse formattando un documento Word...

Si noti anche che le voci Cover e CoverAcknowledgement sono inventate da me ed utilizzate nel template Jinja del mio sito. Infatti, Pelican riconoscerà automaticamente le nuove meta informazioni e creerà delle variabili ad esse associate per usarle nel template HTML con Jinja.

Ci noti anche che la voce category non è definita, perchè ho configurato Pelican in modo da ricavarla automaticamente dal nome della directory in cui ho rigistrato il file. Inoltre, i campi authors e lang non sono definiti perché li ho definiti come variabili globali per il sito. Infine, la voce summary non è definita e perciò, lascio a Pelican la possibilità di ricavarne una estraendo automaticamente i primi X caratteri dal testo principale.

Nel mio sito, i file di pagine ed articoli, hanno estensione “.md” perché ho scelto di formattare i testi con “Markdown”; tuttavia questa non è l’unica opzione, ed è infatti possibile usare la specifica “reStructuredText” o direttamente l’HTML; nel mio caso, preferisco usare MarkDown, perché secondo me è più semplice ed elegante.

Per specificare che un articolo o una pagina sono formattate con MarkDown, il file deve avere estensione “.md”, “.markdown”, “.mkd” o “.mdown”. Un testo formattato con Markdown può specificare link ad altre pagine oppure a “file generici”, specificando la keyword {filename} come nel seguente esempio:

[testo linkato]({filename}relative/path/to/file)

Pelican supporta anche le estensioni di MarkDown; per esempio, l’estensione di MarkDown CodeHilite permette di colorare blocchi di codice per evidenziarne la sintassi. CodeHilite prevede due modi per evidenziare la sintassi: con e senza numerazione delle righe.

Con numerazione delle righe:

1
print("The path-less shebang syntax *will* show line numbers.")

Senza numerazione di righe:

print("The triple-colon syntax will *not* show line numbers.")

L’identificatore del linguaggio (python) può variare in base ai lexers supportati.

I file di testi e articoli vengono salvati nella sottocartella del progetto Pelican denominata content: all’interno di questa cartella possono essere definite delle sottocartelle secondo la configurazione del progetto definita in pelicanconf.py.

Per esempio, le “pagine” di questo sito sono salvate nella sottocartella pages di content ed il file di configurazione pelicanconf.py contiene la seguente impostazione:

PAGE_PATHS = ['pages']

Creare siti multi lingua

Pelican usa i metadati “lang” e “slug”, nonché la variabile di configurazione DEFAULT_LANG per determinare se si tratta di una traduzione; così, se Pelican trova che se esistono due o più file con il medesimo “slug” ma “lang” diversi, può creare un link per saltare da una traduzione all’altro con il seguente codice nel template HTML di Jinja:

{% macro translations_for(article) %}
{% if article.translations %}
Translations:
    {% for translation in article.translations %}
        <a href="{{ SITEURL }}/{{ translation.url }}">{{ translation.lang }}</a>
    {% endfor %}
{% endif %}
{% endmacro %}

Però, a me non è piaciuta questa soluzione perché preferisco creare una un sito completo in una lingua diversa. Così, ho creato la versione inglese di questo sito con il plugin i18n_subsites. Per usarlo, vedi l’articolo Usare i Plugin di Pelican.

Configurare un sito Pelican

La configurazione del sito Pelican dipende dai files pelicanconf.py e publishconf.py; entrambi vengono generati durante l’inizializzazione del progetto pelican con:

> pelican-quickstart

Il file pelicanconf.py contiene le configurazioni del sito per la macchina locale, usata in fase di sviluppo e test del sito; l’altro file, è invece usato per registrare le impostazioni di produzione. Per esempio, per ipertesti.com ho impostato questi file di configurazione.

File pelicanconf.py :

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals

# General settings
USE_FOLDER_AS_CATEGORY = True
DISPLAY_PAGES_ON_MENU = True
DISPLAY_CATEGORIES_ON_MENU = True
DELETE_OUTPUT_DIRECTORY = True
OUTPUT_RETENTION = [".hg", ".git", ".bzr"]
JINJA_ENVIRONMENT = {'trim_blocks': True, 'lstrip_blocks': True}
JINJA_FILTERS = {}
READERS = {'html': None}
MARKDOWN = {
    'extension_configs': {
        'markdown.extensions.codehilite': {'css_class': 'highlight'},
        'markdown.extensions.extra': {},
        'markdown.extensions.meta': {},
    },
    'output_format': 'html5',
}
OUTPUT_PATH = 'output/'
PATH = 'content'
PAGE_PATHS = ['pages']
ARTICLE_PATHS = ['articles']
PLUGINS = ['pelican-plugins.i18n_subsites',]
SITENAME = 'IpeRteSTi'
SITEURL = 'http://localhost:8000'
IMAGES_DOMAIN = SITEURL
STATIC_PATHS = ['images', 'pdfs', 'robots.txt', 'favicon.ico','en/favicon.ico','2950849.html','googlefa35553642c707fa.html']
TYPOGRIFY = True
TYPOGRIFY_IGNORE_TAGS = []
WITH_FUTURE_DATES = False
SLUGIFY_SOURCE = 'basename'
FORMATTED_FIELDS = ['summary', 'coveracknowledgement']

# URL settings
RELATIVE_URLS = True
ARTICLE_URL = 'blog/{category}/{slug}.html'
ARTICLE_SAVE_AS = 'blog/{category}/{slug}.html'
ARTICLE_LANG_URL = '{lang}/blog/{category}/{slug}.html'
ARTICLE_LANG_SAVE_AS = '{lang}/blog/{category}/{slug}.html'
DRAFT_URL = 'blog/{category}/_{slug}_draft.html'
DRAFT_SAVE_AS = '{lang}/blog/{category}/_{slug}_draft.html'
DRAFT_LANG_URL = '{lang}/blog/{category}/_{slug}_draft.html'
DRAFT_LANG_SAVE_AS = '{lang}/blog/{category}/_{slug}_draft.html'
PAGE_URL = 'pages/{slug}.html'
PAGE_SAVE_AS = 'pages/{slug}.html'
PAGE_LANG_URL = '{lang}/pages/{slug}.html'
PAGE_LANG_SAVE_AS = '{lang}/pages/{slug}.html'
CATEGORY_URL = 'category_{slug}.html'
CATEGORY_SAVE_AS = 'category_{slug}.html'
TAG_URL = 'tag_{slug}.html'
TAG_SAVE_AS = 'tag_{slug}.html'
AUTHOR_URL = 'author_{slug}.html'
AUTHOR_SAVE_AS = 'author_{slug}.html'
YEAR_ARCHIVE_SAVE_AS = 'archive_{date:%Y}.html'
MONTH_ARCHIVE_SAVE_AS = 'archive_{date:%Y}_{date:%b}.html'
ARCHIVES_SAVE_AS = 'archives.html'
ARCHIVES_URL = 'archives.html'
CATEGORIES_SAVE_AS = 'categories.html'
CATEGORIES_URL = 'categories.html'
TAGS_SAVE_AS = 'tags.html'
TAGS_URL = 'tags.html'

# Time and Date
TIMEZONE = "Europe/Rome"
DEFAULT_DATE_FORMAT = '%A, %d <span class="text-uppercase">%B</span> %Y'
DATE_FORMATS = {
    'en': ('usa','%A, %d <span class="text-uppercase">%B</span> %Y'),
    'it': ('ita','%A, %d <span class="text-uppercase">%B</span> %Y'),
}
LOCALE = (
    'usa', 'jpn',      # On Windows
    'en_US', 'ja_JP'   # On Unix/Linux
)

# Template pages
TEMPLATE_PAGES = {}
DIRECT_TEMPLATES = ['index', 'categories', 'tags', 'authors', 'archives']
PAGINATED_DIRECT_TEMPLATES = ['index']

# Metadata
AUTHOR = 'Roberto Fusi'
FILENAME_METADATA = '(?P<lang>\D{2})_(?P<date>\d{4}-\d{2}-\d{2})_(?P<slug>.*)'
EXTRA_PATH_METADATA = {
    'images': {'path': 'images/'},
    'pdfs': {'path': 'pdfs/'},
    'robots.txt': {'path': 'robots.txt'},
    'favicon.ico': {'path': 'favicon.ico'},
    'en/favicon.ico': {'path': 'en/favicon.ico'},
    '2950849.html': {'path': '2950849.html'},
    'googlefa35553642c707fa.html': {'path': 'googlefa35553642c707fa.html'},
}

# Feed generation is usually not desired when developing
FEED_DOMAIN = SITEURL
FEED_ALL_ATOM = 'feeds/all.atom.xml'
FEED_ALL_RSS = 'feeds/all.rss.xml'

# Pagination
DEFAULT_PAGINATION = 10

# Translations
DEFAULT_LANG = 'it'

# Themes
THEME = "C:\\Users\\rfusi\OneDrive\Projects\\ipertesti.com\\themes\\ipertesti"
THEME_STATIC_DIR = 'theme'
THEME_STATIC_PATHS = ['static']
CSS_FILE = 'main.css'
SITESUBTITLE = 'Progetti nel WEB'
SITEDESCRIPTION = 'Gli appunti di Roberto Fusi sulla realizzazione di progetti web: Internet, Web Development e Digital Marketing'
MENUITEMS = (('Autore', SITEURL + '/pages/autore.html'),
             ('Contatti', SITEURL + '/pages/contatti.html'),
             ('', ''),
             ('Archivi', SITEURL + '/archives.html'),
             ('Tags', SITEURL + '/tags.html'),)
LINKS = (('Pelican', 'http://getpelican.com/'),
         ('Python', 'http://python.org/'),
         ('Jinja2', 'http://jinja.pocoo.org/'),
         ('GitHub', 'https://github.com/'),
        )

SOCIAL = (('LinkedIn', 'https://www.linkedin.com/in/robertofusi/'),
          ('Twitter', 'https://twitter.com/fusiro'),
          ('GooglePlus', 'https://plus.google.com/111868610859655207227'),
          )

# Reading only modified content
LOAD_CONTENT_CACHE = False
CACHE_PATH = 'cache'
CHECK_MODIFIED_METHOD = 'mtime'
CACHE_CONTENT = False
CONTENT_CACHING_LAYER = 'reader'
GZIP_CACHE = True
WRITE_SELECTED = []

# Plugins configuration
I18N_SUBSITES = {
  'en': {
      'SITENAME': 'IpeRteSTi',
      'SITEURL': 'http://localhost:8000/en',
      'SITESUBTITLE': 'Projects in the WEB',
      'MENUITEMS': (
        ('Author', SITEURL + '/pages/author.html'),
        ('Contacts', SITEURL + '/pages/contacts.html'),
        ('', ''),
        ('Archives', '/en/archives.html'),
        ('Tags', '/en/tags.html'),),
  },
}

File publishconf.py :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals

# This file is only used if you use `make publish` or
# explicitly specify it as your config file.

import os
import sys
sys.path.append(os.curdir)
from pelicanconf import *

SITEURL = 'http://www.ipertesti.com'
IMAGES_DOMAIN = SITEURL
RELATIVE_URLS = False
FEED_DOMAIN = SITEURL
DELETE_OUTPUT_DIRECTORY = True
DISQUS_SITENAME = 'ipertesti-1'
GOOGLE_ANALYTICS = 'UA-43298418-2'
SHARETHIS_PROPERTY = '58f22218dec37d0012242254'

MENUITEMS = (('Autore', SITEURL + '/pages/autore.html'),
             ('Contatti', SITEURL + '/pages/contatti.html'),
             ('', ''),
             ('Archivi', SITEURL + '/archives.html'),
             ('Tags', SITEURL + '/tags.html'),)

# Plugins configuration
I18N_SUBSITES = {
  'en': {
      'SITEURL': SITEURL + '/en',
      'MENUITEMS': (
        ('Author', SITEURL + '/pages/author.html'),
        ('Contacts', SITEURL + '/pages/contacts.html'),
        ('', ''),
        ('Archives', SITEURL + '/en/archives.html'),
        ('Tags', SITEURL + '/en/tags.html'),),
  },
}

Si noti che publishconf.py eredita la maggior parte delle impostazioni di pelicanconf.py grazie all’istruzione “from pelicanconf import *”.

Stili grafici

Durante l’installazione di Pelican, vengono scaricati i temi predefiniti “notmyidea” e “simple”; vi sono molti altri temi già pronti, creati da vari designer e scaricabili dal web; per usarli, basta copiarli da GitHub nella cartella themes del progetto Pelican.

> md themes
> git clone --recursive https://github.com/getpelican/pelican-themes themes

Ho apprezzato molto i temi “attila”, “chunck”, “nest” disponibili su GitHub; é possibile visualizzare una anteprima di questi ed altri temi per Pelican su Pelican Themes.

Per usare un particolare tema, occorre impostare la variabile THEME nel file pelicanconf.py

THEME = "/home/user/pelican-themes/theme-name"

Oppure, si può specificare il tema da usare al momento della generazione dell’output.

> pelican content -s pelicanconf.py -t /projects/your-site/themes/your-theme

Pelican si appoggia su Jinja per definire i modelli delle pagine web, da interpretare in fase di generazione dell’output statico HTML/JAVSCRIPT/CSS del sito web.

Un tema Pelican consiste in una collezione di file salvati in una directory con una struttura simile alla sequente:

├── static
│   ├── css
│   └── images
└── templates
    ├── archives.html         // to display archives
    ├── period_archives.html  // to display time-period archives
    ├── article.html          // processed for each article
    ├── author.html           // processed for each author
    ├── authors.html          // must list all the authors
    ├── categories.html       // must list all the categories
    ├── category.html         // processed for each category
    ├── index.html            // the index (list all the articles)
    ├── page.html             // processed for each page
    ├── tag.html              // processed for each tag
    ├── tags.html             // must list all the tags. Can be a tag cloud
    └── base.html             // html/javascript/css baseline for all the web pages...

Nei file “.html” del tema, sono usati speciali marcatori interpretati da Jinja, per sostituirli con un particolare output. Il modo più semplice per creare un nuovo template è copiarne uno e modificarlo. Come suggerito dalla guida ufficiale; un ottimo punto di partenza è il template “notmyidea”.

Per prima cosa, occorre mettere mano al file “base.html”, in quanto è richiamato da tutti gli altri template, ovvero definisce la struttura di base per tutte le altre pagine web.

Pubblicazione del sito

La pubblicazione di un sito web creato con Pelican, è una operazione veramente veloce ed efficiente. Dopo aver creato i contenuti, generato e testato i file del sito per l’ambiente di test, secondo la configurazione di “pelicanconf.py”, si può rigenerare i file nella cartella output/ secondo le impostazioni di “publishconf.py” con questa istruzione:

pelican content -s publishconf.py

A questo punto, per mettere online il sito, non si deve far altro che trasferire i file della cartella output/ sul server web online, usando il proprio programma preferito (FTP, SSH, RSYNC, etc…).

Pelican, supporta Fabric! per semplificare quanto più possibile il processo di rigenerazione, test e trasferimento dei file del sito. Nella cartella del progetto, si noti la presenza del file fabfile.py che contiene le impostazioni di Fabric!, generate dal comando pelican-quickstart. Nel file fabfile.py occorre verificare l’impostazione delle seguenti variabili:

env.deploy_path = 'output'
production = '[username]@[IP_server]:[port#]'
dest_path = '/absolute/path/to/the/directory/to/serve/as/website'

Siccome uso Python 3.5.2 ho dovuto modificare il nome della libreria socketserver ovvero riscrivere il nome tutto in minuscolo; a parte questo, non ho riscontrato ulteriori problemi.

Pelican usa RSYNC per trasferire i file sul server web remoto; il processo é quindi estremamente veloce. Se è tutto corretto, basterà eseguire i seguenti comandi per mettere online il sito!

fabric clean
fabric preview
fabric publish

Ps. provare fabric -h per ottenere spiegazioni circa gli altri comandi fabric disponibili!

Riferimenti

  1. WikiPedia MS FrontPage
  2. WikiPedia Dreamweaver
  3. Server Side Include
  4. Python
  5. Documentazione pip
  6. Jinja
  7. Pelican
  8. Pelican Themes
  9. Fabric!
  10. Pelican Issues

Libri suggeriti

Condividi questo articolo

Se ti è piaciuto questo articolo e pensi possa essere utile anche ad altri, condividilo con i tuoi amici e conoscenti, facendo click sui pulsanti dei tuoi social network preferiti.

P.S. Grazie!

Commenti

Cosa pensi di questo articolo? Hai dei suggerimenti da darmi o vuoi segnalare la tua esperienza in questa pagina? Registrati con Disqus ed inserisci il tuo commento qui sotto!

Inoltre, se lo desideri puoi anche scrivermi una e-mail.

Presentazione

IpeRteSTi é un blog curato da Roberto Fusi. Raccoglie suggerimenti ed esperienze personali riguardo Internet, Web Development e Digital Marketing.

Seguimi sui social

LinkedInTwitterGooglePlusFeedburner for IpeRteSTi

Iscriviti alla mia newsletter