4
votes

I am building a setup that will contain a main site and a number of microsites. Each microsite is going to have a separate branding but use the same page types.

Given Wagtail already has a Site object which links to an appropriate Page tree, is there also built in functionality to configure the template loaders to choose an appropriate base.html or will I have to write a custom template loader?

2

2 Answers

8
votes

Wagtail doesn't have any built-in functionality for this, as it doesn't make any assumptions about how your templates are put together. However, you could probably implement this yourself fairly easily using the wagtail.contrib.settings module, which provides the ability to attach custom properties to individual sites. For example, you could define a TemplateSettings model with a base_template field - your templates can then check this setting and dynamically extend the appropriate template, using something like:

{% load wagtailsettings_tags %}
{% get_settings %}
{% extends settings.my_app.TemplateSettings.base_template %}
6
votes

I extended the above answer to provide an override of the {% extends ... %} tag to use a template_dir parameter.

myapp.models:

from wagtail.contrib.settings.models import BaseSetting, register_setting

@register_setting
class SiteSettings(BaseSetting):
    """Site settings for each microsite."""

    # Database fields
    template_dir = models.CharField(max_length=255,
                                    help_text="Directory for base template.")

    # Configuration
    panels = ()

myapp.templatetags.local:

from django import template
from django.core.exceptions import ImproperlyConfigured
from django.template.loader_tags import ExtendsNode
from django.template.exceptions import TemplateSyntaxError


register = template.Library()


class SiteExtendsNode(ExtendsNode):
    """
    An extends node that takes a site.
    """

    def find_template(self, template_name, context):

        try:
            template_dir = \
                context['settings']['cms']['SiteSettings'].template_dir
        except KeyError:
            raise ImproperlyConfigured(
                "'settings' not in template context. "
                "Did you forget the context_processor?"
            )

        return super().find_template('%s/%s' % (template_dir, template_name),
                                     context)


@register.tag
def siteextends(parser, token):
    """
    Inherit a parent template using the appropriate site.
    """

    bits = token.split_contents()

    if len(bits) != 2:
        raise TemplateSyntaxError("'%s' takes one argument" % bits[0])

    parent_name = parser.compile_filter(bits[1])
    nodelist = parser.parse()

    if nodelist.get_nodes_by_type(ExtendsNode):
        raise TemplateSyntaxError(
            "'%s' cannot appear more than once in the same template" % bits[0])

    return SiteExtendsNode(nodelist, parent_name)

myproject.settings:

TEMPLATES = [
    {
        ...
        'OPTIONS': {
            ...
            'builtins': ['myapp.templatetags.local'],
        },
    },
]