settings.rst 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. .. _settings:
  2. =============
  3. Site settings
  4. =============
  5. 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.
  6. To use these settings, you must add ``wagtail.contrib.settings`` to your ``INSTALLED_APPS``:
  7. .. code-block:: python
  8. INSTALLED_APPS += [
  9. 'wagtail.contrib.settings',
  10. ]
  11. Defining settings
  12. =================
  13. Create a model that inherits from ``BaseSetting``, and register it using the ``register_setting`` decorator:
  14. .. code-block:: python
  15. from django.db import models
  16. from wagtail.contrib.settings.models import BaseSetting, register_setting
  17. @register_setting
  18. class SocialMediaSettings(BaseSetting):
  19. facebook = models.URLField(
  20. help_text='Your Facebook page URL')
  21. instagram = models.CharField(
  22. max_length=255, help_text='Your Instagram username, without the @')
  23. trip_advisor = models.URLField(
  24. help_text='Your Trip Advisor page URL')
  25. youtube = models.URLField(
  26. help_text='Your YouTube channel or user account URL')
  27. A 'Social media settings' link will appear in the Wagtail admin 'Settings' menu.
  28. .. _edit_handlers_settings:
  29. Edit handlers
  30. -------------
  31. Settings use edit handlers much like the rest of Wagtail. Add a ``panels`` setting to your model defining all the edit handlers required:
  32. .. code-block:: python
  33. @register_setting
  34. class ImportantPages(BaseSetting):
  35. donate_page = models.ForeignKey(
  36. 'wagtailcore.Page', null=True, on_delete=models.SET_NULL, related_name='+')
  37. sign_up_page = models.ForeignKey(
  38. 'wagtailcore.Page', null=True, on_delete=models.SET_NULL, related_name='+')
  39. panels = [
  40. PageChooserPanel('donate_page'),
  41. PageChooserPanel('sign_up_page'),
  42. ]
  43. You can also customize the editor handlers :ref:`like you would do for Page model <customising_the_tabbed_interface>`
  44. with a custom ``edit_handler`` attribute:
  45. .. code-block:: python
  46. from wagtail.admin.edit_handlers import TabbedInterface, ObjectList
  47. @register_setting
  48. class MySettings(BaseSetting):
  49. # ...
  50. first_tab_panels = [
  51. FieldPanel('field_1'),
  52. ]
  53. second_tab_panels = [
  54. FieldPanel('field_2'),
  55. ]
  56. edit_handler = TabbedInterface([
  57. ObjectList(first_tab_panels, heading='First tab'),
  58. ObjectList(second_tab_panels, heading='Second tab'),
  59. ])
  60. Appearance
  61. ----------
  62. You can change the label used in the menu by changing the :attr:`~django.db.models.Options.verbose_name` of your model.
  63. You can add an icon to the menu by passing an 'icon' argument to the ``register_setting`` decorator:
  64. .. code-block:: python
  65. @register_setting(icon='placeholder')
  66. class SocialMediaSettings(BaseSetting):
  67. class Meta:
  68. verbose_name = 'social media accounts'
  69. ...
  70. For a list of all available icons, please see the :ref:`styleguide`.
  71. Using the settings
  72. ==================
  73. Settings are designed to be used both in Python code, and in templates.
  74. Using in Python
  75. ---------------
  76. If you require access to a setting in a view, the :func:`~wagtail.contrib.settings.models.BaseSetting.for_request` method allows you to retrieve the relevant settings for the current request:
  77. .. code-block:: python
  78. def view(request):
  79. social_media_settings = SocialMediaSettings.for_request(request)
  80. ...
  81. In places where the request is unavailable, but you know the ``Site`` you wish to retrieve settings for, you can use :func:`~wagtail.contrib.settings.models.BaseSetting.for_site` instead:
  82. .. code-block:: python
  83. social_media_settings = SocialMediaSettings.for_site(user.origin_site)
  84. Using in Django templates
  85. -------------------------
  86. Add the ``settings`` context processor to your settings:
  87. .. code-block:: python
  88. TEMPLATES = [
  89. {
  90. ...
  91. 'OPTIONS': {
  92. 'context_processors': [
  93. ...
  94. 'wagtail.contrib.settings.context_processors.settings',
  95. ]
  96. }
  97. }
  98. ]
  99. Then access the settings through ``{{ settings }}``:
  100. .. code-block:: html+django
  101. {{ settings.app_label.SocialMediaSettings.instagram }}
  102. .. note:: Replace ``app_label`` with the label of the app containing your settings model.
  103. 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 %}``:
  104. .. code-block:: html+django
  105. {% load wagtailsettings_tags %}
  106. {% get_settings %}
  107. {{ settings.app_label.SocialMediaSettings.instagram }}
  108. If there is no ``request`` available in the template at all, you can use the settings for the default Wagtail site instead:
  109. .. code-block:: html+django
  110. {% load wagtailsettings_tags %}
  111. {% get_settings use_default_site=True %}
  112. {{ settings.app_label.SocialMediaSettings.instagram }}
  113. .. 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.
  114. By default, the tag will create or update a ``settings`` variable in the context. If you want to
  115. assign to a different context variable instead, use ``{% get_settings as other_variable_name %}``:
  116. .. code-block:: html+django
  117. {% load wagtailsettings_tags %}
  118. {% get_settings as wagtail_settings %}
  119. {{ wagtail_settings.app_label.SocialMediaSettings.instagram }}
  120. .. _settings_tag_jinja2:
  121. Using in Jinja2 templates
  122. -------------------------
  123. Add ``wagtail.contrib.settings.jinja2tags.settings`` extension to your Jinja2 settings:
  124. .. code-block:: python
  125. TEMPLATES = [
  126. # ...
  127. {
  128. 'BACKEND': 'django.template.backends.jinja2.Jinja2',
  129. 'APP_DIRS': True,
  130. 'OPTIONS': {
  131. 'extensions': [
  132. # ...
  133. 'wagtail.contrib.settings.jinja2tags.settings',
  134. ],
  135. },
  136. }
  137. ]
  138. Then access the settings through the ``settings()`` template function:
  139. .. code-block:: html+jinja
  140. {{ settings("app_label.SocialMediaSettings").twitter }}
  141. .. note:: Replace ``app_label`` with the label of the app containing your settings model.
  142. 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:
  143. .. code-block:: html+jinja
  144. {{ settings("app_label.SocialMediaSettings", use_default_site=True).instagram }}
  145. You can store the settings instance in a variable to save some typing, if you have to use multiple values from one model:
  146. .. code-block:: html+jinja
  147. {% with social_settings=settings("app_label.SocialMediaSettings") %}
  148. Follow us on Twitter at @{{ social_settings.twitter }},
  149. or Instagram at @{{ social_settings.instagram }}.
  150. {% endwith %}
  151. Or, alternately, using the ``set`` tag:
  152. .. code-block:: html+jinja
  153. {% set social_settings=settings("app_label.SocialMediaSettings") %}
  154. Utilising ``select_related`` to improve efficiency
  155. --------------------------------------------------
  156. For models with foreign key relationships to other objects (e.g. pages),
  157. which are very often needed to output values in templates, you can set
  158. the ``select_related`` attribute on your model to have Wagtail utilise
  159. Django's `QuerySet.select_related() <https://docs.djangoproject.com/en/stable/ref/models/querysets/#select-related>`_
  160. method to fetch the settings object and related objects in a single query.
  161. With this, the initial query is more complex, but you will be able to
  162. freely access the foreign key values without any additional queries,
  163. making things more efficient overall.
  164. Building on the ``ImportantPages`` example from the previous section, the
  165. following shows how ``select_related`` can be set to improve efficiency:
  166. .. code-block:: python
  167. :emphasize-lines: 4,5
  168. @register_setting
  169. class ImportantPages(BaseSetting):
  170. # Fetch these pages when looking up ImportantPages for or a site
  171. select_related = ["donate_page", "sign_up_page"]
  172. donate_page = models.ForeignKey(
  173. 'wagtailcore.Page', null=True, on_delete=models.SET_NULL, related_name='+')
  174. sign_up_page = models.ForeignKey(
  175. 'wagtailcore.Page', null=True, on_delete=models.SET_NULL, related_name='+')
  176. panels = [
  177. PageChooserPanel('donate_page'),
  178. PageChooserPanel('sign_up_page'),
  179. ]
  180. With these additions, the following template code will now trigger
  181. a single database query instead of three (one to fetch the settings,
  182. and two more to fetch each page):
  183. .. code-block:: html+django
  184. {% load wagtailcore_tags %}
  185. {% pageurl settings.app_label.ImportantPages.donate_page %}
  186. {% pageurl settings.app_label.ImportantPages.sign_up_page %}
  187. Utilising the ``page_url`` setting shortcut
  188. -------------------------------------------
  189. If, like in the previous section, your settings model references pages,
  190. and you often need to output the URLs of those pages in your project,
  191. you can likely use the setting model's ``page_url`` shortcut to do that more
  192. cleanly. For example, instead of doing the following:
  193. .. code-block:: html+django
  194. {% load wagtailcore_tags %}
  195. {% pageurl settings.app_label.ImportantPages.donate_page %}
  196. {% pageurl settings.app_label.ImportantPages.sign_up_page %}
  197. You could write:
  198. .. code-block:: html+django
  199. {{ settings.app_label.ImportantPages.page_url.donate_page }}
  200. {{ settings.app_label.ImportantPages.page_url.sign_up_page }}
  201. Using the ``page_url`` shortcut has a few of advantages over using the tag:
  202. 1. The 'specific' page is automatically fetched to generate the URL,
  203. so you don't have to worry about doing this (or forgetting to do this)
  204. yourself.
  205. 2. The results are cached, so if you need to access the same page URL
  206. in more than one place (e.g. in a form and in footer navigation), using
  207. the ``page_url`` shortcut will be more efficient.
  208. 3. It's more concise, and the syntax is the same whether using it in templates
  209. or views (or other Python code), allowing you to write more consistent
  210. code.
  211. When using the ``page_url`` shortcut, there are a couple of points worth noting:
  212. 1. The same limitations that apply to the `{% pageurl %}` tag apply to the
  213. shortcut: If the settings are accessed from a template context where the
  214. current request is not available, all URLs returned will include the
  215. site's scheme/domain, and URL generation will not be quite as efficient.
  216. 2. If using the shortcut in views or other Python code, the method will
  217. raise an ``AttributeError`` if the attribute you request from ``page_url``
  218. is not an attribute on the settings object.
  219. 3. If the settings object DOES have the attribute, but the attribute returns
  220. a value of ``None`` (or something that is not a ``Page``), the shortcut
  221. will return an empty string.