Variabili di contesto
Contesto globale
Disponibile in ogni template (layout, sezioni, pagine).
| Variabile | Tipo | Note |
|---|---|---|
current_url | stringa | URL assoluto della richiesta |
organization | organizzazione | vedi Oggetti |
supporter | sostenitore o None | sostenitore che ha effettuato l'accesso |
supporter_urls.login | stringa | URL di accesso |
supporter_urls.logout | stringa | URL di uscita |
supporter_urls.dashboard | stringa | area riservata del sostenitore |
supporter_urls.profile | stringa | profilo del sostenitore |
supporter_urls.donations | stringa | donazioni del sostenitore |
supporter_urls.campaigns | stringa | campagne del sostenitore |
pages | elenco pagine | tutte le pagine pubblicate |
campaigns | elenco campagne | tutte le campagne |
menus | elenco menu | |
menuitems | elenco voci di menu | |
blogs | elenco blog | |
articles | elenco articoli |
Gli elenchi globali (campaigns, pages, blogs, articles) espongono gli
attributi di base di ciascun elemento. La variabile della pagina corrente
(campaign, page, blog, article, project) espone tutti gli attributi
descritti in Oggetti e attributi.
Variabili per tipo di pagina
Ogni vista aggiunge le proprie variabili al contesto globale.
| Pagina | Template | Variabili aggiuntive |
|---|---|---|
| Campagna | campaign | campaign; se campagna Lead anche form, custom_field_definitions, lead_form_success, captcha |
| Ringraziamento | thankyou | checkout_campaign, checkout_campaign_url, checkout_supporter, checkout_donation, message_published, form |
| Peer campaign | peer_campaign | campaign, peer_campaign, stats |
| Form peer campaign | peer_campaign_form | form, supporter, campaign, peer_campaign (None in creazione) |
| Gestione peer campaign (v2) | peer_campaign_form | come sopra, più stats, peer_campaign_updated, peer_campaign_public_url, peer_campaign_update_url_v2 |
Il form della peer campaign ha due soli campi, peer_supporter_name e
custom_message. Lo slug non si chiede: viene derivato dal nome con lo stesso
contratto delle altre slug (slugify più suffisso numerico finché è libero) e non
è modificabile dopo, perché è l'indirizzo che il promotore ha già condiviso.
Lo stesso template rende tre pagine, distinte da peer_campaign:
campaigns/<slug>/fundraise/— creazione,peer_campaignèNone. Risponde 404 se la campagna non prevede raccolte personali o è di tipo Lead, prima ancora di chiedere l'accesso;campaigns/<slug>/<peer_slug>/update/v2/— la pagina di dettaglio e gestione della propria raccolta, con le statistiche e il form precompilato. Il form va inviato in POST apeer_campaign_update_url_v2, e dopo un salvataggio riuscito la vista ritorna qui conpeer_campaign_updatedaTrue;campaigns/<slug>/<peer_slug>/update/— la v1 della modifica, ancora attiva e con il comportamento di prima: dopo il salvataggio manda alla pagina pubblica e non passa le variabili aggiuntive. I temi nuovi puntano alla v2, che trovano anche inpeer_campaign.update_url_v2.
La pagina che il tema linka non è più nessuna di queste due: è
/my/campaigns/<id>/, dentro l'area sostenitore, descritta più sotto. La v2
resta servita perché è la action del form dei temi rilasciati prima dello
spostamento.
peer_campaign_public_url è assoluta e senza __preview: è l'indirizzo da
condividere. peer_campaign_update_url_v2 è relativa e conserva __preview,
perché è la destinazione di un form.
Disattivare le raccolte personali sulla campagna madre chiude la creazione di
nuove pagine, non quelle già aperte: restano pubbliche e il promotore continua a
poterne correggere nome e messaggio.
| Pagina | page | page |
| Blog | blog | blog |
| Articolo | article | article |
| Progetto | project | project |
| Elenco progetti | project_list | projects |
Il template usato è quello del tipo (es. campaign) oppure quello impostato
sul singolo contenuto (campaign.template).
Nella pagina di ringraziamento checkout_supporter.id e checkout_donation.id
sono gli id numerici del sostenitore e della donazione appena registrata: sono
quello che serve ai pixel di conversione e ai dataLayer, un identificativo
stabile e non il nome della persona.
<script>
dataLayer.push({
event: "donation",
donation_id: "{{ checkout_donation.id }}",
supporter_id: "{{ checkout_supporter.id }}",
value: "{{ checkout_donation.amount }}",
});
</script>
Nell'anteprima del tema (.../thankyou/__preview__) non esiste nessun checkout:
i due id valgono 0, come il resto dei dati di esempio.
Area sostenitore
Queste pagine non usano il motore delle sezioni: sono template statici del tema, con il percorso indicato in tabella.
| Pagina | Template | Variabili aggiuntive |
|---|---|---|
| Accesso | templates/supporters/login.html | form, email_sent, email_sent_to, captcha, error |
| Bacheca | templates/supporters/dashboard.html | profile, donations, peer_campaigns |
| Profilo | templates/supporters/profile.html | form, profile, saved |
| Donazioni | templates/supporters/donations.html | profile, donations |
| Campagne | templates/supporters/peer_campaigns.html | profile, peer_campaigns |
| Dettaglio campagna | templates/supporters/peer_campaign.html | form, profile, campaign, peer_campaign, stats, peer_campaign_updated, peer_campaign_public_url, peer_campaign_manage_url |
profile è un supporter, donations un elenco di
donation e peer_campaigns un elenco di
peer_campaign.
Il dettaglio campagna sta su /my/campaigns/<id>/, e ci si arriva da
peer_campaign.manage_url. È indirizzato per id e non per slug perché lo slug di
una raccolta personale è unico dentro la campagna, non dentro l'organizzazione.
Mostra le stesse cose della gestione v2 — statistiche, link da condividere, form
precompilato con nome e messaggio — e il form va inviato in POST a
peer_campaign_manage_url, che è questa stessa pagina con __preview
conservato. Dopo un salvataggio riuscito la vista ritorna qui con
peer_campaign_updated a True. Una raccolta che non è del sostenitore
collegato risponde 404, non 403.
Sono gli stessi oggetti su tutte le pagine. In precedenza la bacheca riceveva
questi oggetti mentre le pagine donazioni e campagne ricevevano queryset: un tema
che chiama donations.all() va aggiornato, ora donations è già un elenco.
error vale token quando il link di accesso è scaduto o già usato: un link
vale una volta sola e per un'ora. La sessione, invece, non scade.
Chi può accedere
Chiunque. Il link parte per qualunque indirizzo valido, anche uno che non ha mai
donato e che l'organizzazione non ha in anagrafica; l'anagrafica viene creata
quando il link viene aperto, non quando viene chiesto. Fa eccezione un
indirizzo archiviato, che riceve error=token come un link non valido:
archiviare è una decisione dell'organizzazione e l'accesso non la annulla.
Il tema non deve quindi promettere condizioni che non esistono («l'indirizzo con cui hai donato»), e non deve dire se l'indirizzo era conosciuto: la risposta è la stessa in ogni caso, altrimenti la pagina di accesso diventa un modo per chiedere al sito di un'organizzazione se una certa persona le ha donato.
Il captcha su templates/supporters/login.html non è opzionale. È un form
pubblico che fa partire una mail dal dominio dell'organizzazione verso un
indirizzo scelto da chi compila: un tema che non rende il widget e l'honeypot
lascia quella porta aperta.
Nei form dell'area disabilita il pulsante al submit e mostra uno stato di attesa,
altrimenti chi non vede una risposta immediata continua a cliccare e invia il
form più volte. Il tema di riferimento lo fa con un data-submit sul pulsante e
un submit listener che imposta form.dataset.submitted.
Protezione antibot (captcha)
Le viste che espongono un form pubblico aggiungono al contesto la variabile
captcha. Se captcha.enabled è false il tema non deve rendere nulla: la
protezione è disattivata per quel form.
Sono tre e sole tre: box lead, checkout e accesso sostenitore. I form dentro l'area riservata non hanno captcha e non devono averlo — il costo lo pagherebbe il donatore, non chi abusa, che per arrivarci ha già fatto l'accesso.
| Attributo | Descrizione |
|---|---|
captcha.enabled | false quando la protezione è disattivata |
captcha.challenge_url | endpoint da cui il widget prende la sfida |
captcha.script_url | unico script da caricare, servito dalla piattaforma |
captcha.algorithm | algoritmo della sfida |
captcha.i18n_url | file di lingua del widget, null se non disponibile |
captcha.language | codice lingua a due lettere |
captcha.field_name | nome del campo che il widget compila |
captcha.honeypot_field | nome del campo esca da rendere invisibile |
{% if captcha.enabled %}
<script type="module" async defer src="{{ captcha.script_url }}"></script>
<altcha-widget challenge="{{ captcha.challenge_url }}"
name="{{ captcha.field_name }}"
language="{{ captcha.language }}"
auto="onfocus"></altcha-widget>
{% endif %}
captcha.script_url e' l'unico script da caricare, e non e' il bundle del widget:
registra anche l'algoritmo della sfida, che il bundle da solo non conosce. Un tema
che punta a altcha.min.js a mano ottiene un widget che fallisce ogni verifica
con "unsupported algorithm". Per lo stesso motivo non esiste piu' worker_url:
l'attributo workerurl non e' mai esistito nel widget e non faceva nulla.
Il campo esca va reso fuori dallo schermo, non con display:none, e con
autocomplete="off" e tabindex="-1", altrimenti il browser lo compila da solo e
blocca una persona vera.
Non scrivere a mano l'endpoint o i percorsi degli asset: leggili sempre da
captcha. Rendi anche form.non_field_errors(), perche' il campo esca compilato
produce un errore di form e non di campo.
Note
- Le variabili SEO (
seo_title,seo_description,google_tag, ...) vivono solo nell'header e non sono accessibili nei template del tema. - La pagina
donateusa un template di sistema e non il motore delle sezioni. supporter_urlsconserva__preview: usa sempre quelle chiavi invece di scrivere i percorsi a mano, altrimenti dall'anteprima del tema si esce al primo clic.