Site settings¶
You can define settings for your site that are editable by administrators in the Wagtail admin. These settings can be accessed in code, as well as in templates.
To use these settings, you must add wagtail.contrib.settings
to your INSTALLED_APPS
:
INSTALLED_APPS += [
'wagtail.contrib.settings',
]
Defining settings¶
Create a model that inherits from BaseSetting
, and register it using the register_setting
decorator:
from django.db import models
from wagtail.contrib.settings.models import BaseSetting, register_setting
@register_setting
class SocialMediaSettings(BaseSetting):
facebook = models.URLField(
help_text='Your Facebook page URL')
instagram = models.CharField(
max_length=255, help_text='Your Instagram username, without the @')
trip_advisor = models.URLField(
help_text='Your Trip Advisor page URL')
youtube = models.URLField(
help_text='Your YouTube channel or user account URL')
A ‘Social media settings’ link will appear in the Wagtail admin ‘Settings’ menu.
Edit handlers¶
Settings use edit handlers much like the rest of Wagtail. Add a panels
setting to your model defining all the edit handlers required:
@register_setting
class ImportantPages(BaseSetting):
donate_page = models.ForeignKey(
'wagtailcore.Page', null=True, on_delete=models.SET_NULL, related_name='+')
sign_up_page = models.ForeignKey(
'wagtailcore.Page', null=True, on_delete=models.SET_NULL, related_name='+')
panels = [
PageChooserPanel('donate_page'),
PageChooserPanel('sign_up_page'),
]
You can also customize the editor handlers like you would do for Page model
with a custom edit_handler
attribute:
from wagtail.admin.edit_handlers import TabbedInterface, ObjectList
@register_setting
class MySettings(BaseSetting):
# ...
first_tab_panels = [
FieldPanel('field_1'),
]
second_tab_panels = [
FieldPanel('field_2'),
]
edit_handler = TabbedInterface([
ObjectList(first_tab_panels, heading='First tab'),
ObjectList(second_tab_panels, heading='Second tab'),
])
Appearance¶
You can change the label used in the menu by changing the verbose_name
of your model.
You can add an icon to the menu by passing an ‘icon’ argument to the register_setting
decorator:
@register_setting(icon='placeholder')
class SocialMediaSettings(BaseSetting):
class Meta:
verbose_name = 'social media accounts'
...
For a list of all available icons, please see the UI Styleguide.
Using the settings¶
Settings are designed to be used both in Python code, and in templates.
Using in Python¶
If you require access to a setting in a view, the for_request()
method allows you to retrieve the relevant settings for the current request:
def view(request):
social_media_settings = SocialMediaSettings.for_request(request)
...
In places where the request is unavailable, but you know the Site
you wish to retrieve settings for, you can use for_site()
instead:
social_media_settings = SocialMediaSettings.for_site(user.origin_site)
Using in Django templates¶
Add the settings
context processor to your settings:
TEMPLATES = [
{
...
'OPTIONS': {
'context_processors': [
...
'wagtail.contrib.settings.context_processors.settings',
]
}
}
]
Then access the settings through {{ settings }}
:
{{ settings.app_label.SocialMediaSettings.instagram }}
Note
Replace app_label
with the label of the app containing your settings model.
If you are not in a RequestContext
, then context processors will not have run, and the settings
variable will not be available. To get the settings
, use the provided {% get_settings %}
template tag. If a request
is in the template context, but for some reason it is not a RequestContext
, just use {% get_settings %}
:
{% load wagtailsettings_tags %}
{% get_settings %}
{{ settings.app_label.SocialMediaSettings.instagram }}
If there is no request
available in the template at all, you can use the settings for the default Wagtail site instead:
{% load wagtailsettings_tags %}
{% get_settings use_default_site=True %}
{{ settings.app_label.SocialMediaSettings.instagram }}
Note
You can not reliably get the correct settings instance for the current site from this template tag if the request object is not available. This is only relevant for multisite instances of Wagtail.
Using in Jinja2 templates¶
Add wagtail.contrib.settings.jinja2tags.settings
extension to your Jinja2 settings:
TEMPLATES = [
# ...
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'APP_DIRS': True,
'OPTIONS': {
'extensions': [
# ...
'wagtail.contrib.settings.jinja2tags.settings',
],
},
}
]
Then access the settings through the settings()
template function:
{{ settings("app_label.SocialMediaSettings").twitter }}
Note
Replace app_label
with the label of the app containing your settings model.
This will look for a request
variable in the template context, and find the correct site to use from that. If for some reason you do not have a request
available, you can instead use the settings defined for the default site:
{{ settings("app_label.SocialMediaSettings", use_default_site=True).instagram }}
You can store the settings instance in a variable to save some typing, if you have to use multiple values from one model:
{% with social_settings=settings("app_label.SocialMediaSettings") %}
Follow us on Twitter at @{{ social_settings.twitter }},
or Instagram at @{{ social_settings.Instagram }}.
{% endwith %}
Or, alternately, using the set
tag:
{% set social_settings=settings("app_label.SocialMediaSettings") %}
Utilising the page_url
setting shortcut¶
New in version 2.10.
If, like in the previous section, your settings model references pages,
and you regularly need to output the URLs of those pages in your project,
you can likely use the setting model’s page_url
shortcut to do that more
cleanly. For example, instead of doing the following:
{% load wagtailcore_tags %}
{% pageurl settings.app_label.ImportantPages.donate_page %}
{% pageurl settings.app_label.ImportantPages.sign_up_page %}
You could write:
{{ settings.app_label.ImportantPages.page_url.donate_page }}
{{ settings.app_label.ImportantPages.page_url.sign_up_page }}
Using the page_url
shortcut has a few of advantages over using the tag:
- The ‘specific’ page is automatically fetched to generate the URL, so you don’t have to worry about doing this (or forgetting to do this) yourself.
- The results are cached, so if you need to access the same page URL
in more than one place (e.g. in a form and in footer navigation), using
the
page_url
shortcut will be more efficient. - It’s more concise, and the syntax is the same whether using it in templates or views (or other Python code), allowing you to write more more consistent code.
When using the page_url
shortcut, there are a couple of points worth noting:
- The same limitations that apply to the {% pageurl %} tag apply to the shortcut: If the settings are accessed from a template context where the current request is not available, all URLs returned will include the site’s scheme/domain, and URL generation will not be quite as efficient.
- If using the shortcut in views or other Python code, the method will
raise an
AttributeError
if the attribute you request frompage_url
is not an attribute on the settings object. - If the settings object DOES have the attribute, but the attribute returns
a value of
None
(or something that is not aPage
), the shortcut will return an empty string.