Skip to main content

Context variables

Global context​

Available in every template (layout, sections, pages).

VariableTypeNotes
current_urlstringabsolute URL of the request
organizationorganizationsee Objects
supportersupporter or Nonelogged-in supporter
supporter_urls.loginstringlogin URL
supporter_urls.logoutstringlogout URL
supporter_urls.dashboardstringsupporter private area
supporter_urls.profilestringsupporter profile
supporter_urls.donationsstringsupporter donations
supporter_urls.campaignsstringsupporter campaigns
pageslist of pagesall published pages
campaignslist of campaignsall campaigns
menuslist of menus
menuitemslist of menu items
blogslist of blogs
articleslist of articles
note

The global lists (campaigns, pages, blogs, articles) expose only the basic attributes. The current page variable (campaign, page, blog, article, project) exposes all the ones described in Objects and attributes.

Per-page variables​

PageTemplateAdditional variables
Campaigncampaigncampaign; for a Lead campaign also form, custom_field_definitions, lead_form_success, captcha
Thank youthankyoucheckout_campaign, checkout_campaign_url, checkout_supporter, checkout_donation, message_published, form
Peer campaignpeer_campaigncampaign, peer_campaign, stats
Peer campaign formpeer_campaign_formform, supporter, campaign, peer_campaign (None on creation)
Peer campaign management (v2)peer_campaign_formas above, plus stats, peer_campaign_updated, peer_campaign_public_url, peer_campaign_update_url_v2
Pagepagepage
Blogblogblog
Articlearticlearticle
Projectprojectproject
Project listproject_listprojects

The template used is the one for the type (e.g. campaign) or the one set on the individual content (campaign.template).

Thank you​

checkout_supporter.id and checkout_donation.id are the numeric ids of the supporter and of the donation just recorded, for conversion pixels and dataLayers.

<script>
dataLayer.push({
event: "donation",
donation_id: "{{ checkout_donation.id }}",
supporter_id: "{{ checkout_supporter.id }}",
value: "{{ checkout_donation.amount }}",
});
</script>
note

In the theme preview (.../thankyou/__preview__) both ids are 0, like the rest of the example data.

Peer campaign​

The form has two fields, peer_supporter_name and custom_message. The slug is derived from the name (slugify plus a numeric suffix if taken) and cannot be changed later, because it is the address the promoter has already shared.

The peer_campaign_form template renders three pages, told apart by peer_campaign:

  • campaigns/<slug>/fundraise/: creation, peer_campaign is None. It returns 404, before asking for login, if the campaign does not allow personal fundraisers or is a Lead campaign;
  • campaigns/<slug>/<peer_slug>/update/v2/: detail and management of the fundraiser, with statistics and a prefilled form. The form is sent via POST to peer_campaign_update_url_v2; after a successful save the view returns here with peer_campaign_updated set to True;
  • campaigns/<slug>/<peer_slug>/update/: v1, still active. After saving it redirects to the public page and does not pass the additional variables.

Themes link to /my/campaigns/<id>/ instead, in the supporter area. v2 stays active because it is the form action in themes released earlier.

peer_campaign_public_url is absolute and without __preview: it is the address to share. peer_campaign_update_url_v2 is relative and keeps __preview, because it is a form target.

Disabling personal fundraisers on the parent campaign prevents new ones from being created; existing ones stay public and editable.

Supporter area​

These pages are static theme templates and do not use the sections engine.

PageTemplateAdditional variables
Logintemplates/supporters/login.htmlform, email_sent, email_sent_to, captcha, error
Dashboardtemplates/supporters/dashboard.htmlprofile, donations, peer_campaigns
Profiletemplates/supporters/profile.htmlform, profile, saved
Donationstemplates/supporters/donations.htmlprofile, donations
Campaignstemplates/supporters/peer_campaigns.htmlprofile, peer_campaigns
Campaign detailtemplates/supporters/peer_campaign.htmlform, profile, campaign, peer_campaign, stats, peer_campaign_updated, peer_campaign_public_url, peer_campaign_manage_url

profile is a supporter, donations a list of donation and peer_campaigns a list of peer_campaign.

danger

The donations and campaigns pages used to receive querysets: a theme that calls donations.all() must be updated, donations is now already a list.

The campaign detail lives at /my/campaigns/<id>/ and is reached from peer_campaign.manage_url. It uses the id rather than the slug, because a personal fundraiser's slug is unique only within its campaign. It shows statistics, the link to share and a form prefilled with name and message. The form is sent via POST to peer_campaign_manage_url (the page itself, with __preview kept); after a successful save the view returns here with peer_campaign_updated set to True. A fundraiser belonging to another supporter returns 404.

error is token when the login link has expired or was already used: a link works only once and for one hour. The session does not expire.

Who can log in​

Anyone. The link is sent to any valid address, even one the organization does not know: the supporter record is created when the link is opened. The exception is an archived address, which gets error=token like an invalid link.

The theme must not promise conditions that do not exist ("the address you donated with") nor say whether the address was known: the response is always the same, otherwise the page reveals who donated to the organization.

danger

The captcha on templates/supporters/login.html is mandatory: the form sends an email from the organization's domain to an address chosen by whoever fills it in. The theme must render the widget and the honeypot.

tip

In the area forms, disable the button on submit and show a waiting state, so the form is not sent several times. The reference theme uses a data-submit on the button and a submit listener that sets form.dataset.submitted.

Bot protection (captcha)​

Views with a public form add the captcha variable to the context. If captcha.enabled is false the theme must render nothing.

Three forms are protected: lead box, checkout and supporter login. The private area forms have no captcha, because whoever uses them has already logged in.

AttributeDescription
captcha.enabledfalse when protection is disabled
captcha.challenge_urlendpoint the widget gets the challenge from
captcha.script_urlthe only script to load, served by the platform
captcha.algorithmchallenge algorithm
captcha.i18n_urlwidget language file, null if not available
captcha.languagetwo-letter language code
captcha.field_namename of the field the widget fills in
captcha.honeypot_fieldname of the decoy field to hide
{% 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 %}
danger

Load only captcha.script_url, not the widget bundle: it also registers the challenge algorithm, which the bundle does not know. Pointing to altcha.min.js by hand makes every verification fail with "unsupported algorithm". worker_url no longer exists.

The decoy field goes off screen (not display:none), with autocomplete="off" and tabindex="-1": otherwise the browser fills it in and blocks a real person.

danger

Always read the endpoint and asset paths from captcha, never write them by hand. Also render form.non_field_errors(): a filled decoy field produces a form error, not a field error.

Notes​

  • SEO variables (seo_title, seo_description, google_tag, ...) are used only in the header and are not accessible in theme templates.
  • The donate page uses a system template, not the sections engine.
  • Always use supporter_urls instead of writing paths by hand: they keep __preview, so the first click does not leave the theme preview.