Wagtailでテンプレートを動的に出し分けする

コンテンツの内容により、テンプレートを使い分ける方法を解説します。

Wagtailでテンプレートを動的に出し分けする

同じタイプのページであっても、コンテンツの内容によっては表示の仕方を変えたいことがあります。

例えば、定期的に行うキャンペーンに関するページを作成する場合には、キャンペーンのタイトルや内容の説明などの基本的な部分は同じでも、ページのデザインや配置は別の形にしたいことがあります。その場合は、CampaignPageのようなWagtailのページを作成してデータを管理し、表示用のテンプレートはそれぞれの記事ごとに用意するようなことが考えられます。こうすることで、各種キャンペーンは管理画面で一括管理できる一方で、それぞれのキャンペーン向けに異なるデザインを採用することができます。

Pageモデルのget_template関数の基本

WagtailのPageモデルにはget_template関数が実装されており、この関数をオーバーライドすることによってテンプレートの出し分けを行うことができます。get_template関数はURLにアクセスされてページが表示されるたびに実行されるもので、そのページのPageモデルに関連づけられたテンプレートを返すようになっています。

通常のPageモデルを継承した実装では、以下のようにデフォルトのテンプレートを指定します。Pageモデルで実装されているget_template関数では、templateアトリビュートに指定したテンプレートを利用するようになっているので、テンプレートの出し分けが必要ない場合にはget_template関数は実装する必要はありません。

# models.py

from wagtail.core.models import Page

class CampaignPage(Page):
    """キャンペーン用のページ"""
    ...
    # 以下で指定したテンプレートが適用される
    template = "campaign/default_campaign_page.html"

続いて、get_template関数をオーバーライドして、条件によって利用するテンプレートを出し分けします。

以下の例では、is_special_campaignというBoolean型のアトリビュートを追加し、Trueであれば別のテンプレートを表示するようにします。

# models.py

from django.db import models
from wagtail.core.models import Page

class CampaignPage(Page):
    """キャンペーン用のページ"""
    ...
    template = "campaign/default_campaign_page.html"
    is_special_campaign = models.BooleanField() # 特別なキャンペーンであればTrue

    # get_template関数をオーバーライド
    def get_template(self, request):
        # 特別なキャンペーンであれば専用のテンプレートで表示
        if self.is_special_campaign:
            return 'campaign/special_campaign_page.html'

        return self.template # その他はデフォルトのテンプレートで表示

複数のパターンでテンプレートを出し分けする

簡単なテンプレートの出し分けは、上で解説したような基本的な利用方法で実現可能です。さらに多くのパターンを出し分けしたい場合には、テンプレートのタイプをリスト化して選択できるようにすると良いです。

template_typeというフィールドを追加して、管理画面から選択肢を選べるようにしましょう。

# models.py

from django.db import models
from wagtail.core.models import Page
from wagtail.admin.edit_handlers import FieldPanel

class CampaignPage(Page):
    """キャンペーン用のページ"""
    ...
    template = "campaign/default_campaign_page.html"
    # 利用するテンプレートを選択肢から選べるようにする
    template_type = models.CharField(max_length=255, blank=True, null=True,
                       choices=(("campaign/weekly_campaign_template.html", "Weekly Campaign"),
                                ("campaign/monthly_campaign_template.html", "Monthly Campaign"),
                                ("campaign/quarterly_campaign_template.html", "Quarterly Campaign")))

    # 管理画面から選択できるようにする
    content_panels = Page.content_panels + [
        ...
        FieldPanel("template_type"),
    ]

    # get_template関数をオーバーライド
    def get_template(self, request):
        # テンプレートタイプの指定があればそのテンプレートを使う
        if self.template_type is not None:
            return self.template_type

        return self.template

Wagtailで動的にテンプレートを出し分けする方法を紹介しました。Pageモデルのget_templateメソッドをオーバーライドすればテンプレートの出し分け条件を細かく設定することも可能です。

状況によっては、テンプレート内で条件分岐して表示を変える方が簡単な場合もあると思いますが、ページごと丸々表示を変えたい場合はこちらの方法を選択すると良いでしょう。