Wagtailで自由度の高い外部リンクを設定できるようにする[wagtail-draftail-snippet]
Wagtailの外部リンクの挿入で、relやtargetなどの属性を柔軟に設定できるようにします。
Wagtailではリンクの挿入が簡単にできるようになっていますが、外部のリンクを設定する際にはそのリンク先(href)の設定しかできません。例えばrel="nofollow"
やtarget="_blank"
といった属性をリンクに追加することができません。
そのため、特定のタグを含めたキャンペーン用のリンクやアフィリエイト用のリンクを設定することができず、メディアの運営で不便なことがあります。また、アフィリエイトなどで同じ商品のリンクのURLが変わったりする場合にも、サイト内に多くのリンクを仕込んでいると修正が大変になります。リンクのパラメータを自由に設定でき、テンプレートのような形で保存しておいて使いまわせるような仕組みがあると便利です。
これは、wagtail-draftail-snippetというライブラリで解決できます。
WagtailにはSnippetと呼ばれる機能がありますが、このSnippetの機能を拡張してカスタマイズしたリンクを簡単に挿入できるようにするものになります。
インストール
pipでパッケージをインストールします。
$ pip install wagtail-draftail-snippet
settings.pyの変更
wagtail_draftail_snippet
をsettings.py
ファイルのINSTALLED_APPS
に追加します。
# settings.py
INSTALLED_APPS = [
...
'wagtail_draftail_snippet',
...
]
RichTextBlockのfeaturesの設定
Wagtailでは、featuresという引数でRichTextBlockで利用できる機能を制限することができます。そのfeatures引数の中に、"snippet-link"
という値を設定しましょう。
# models.py
# RichTextFieldで直接利用する場合の例
body = RichTextField(features=["bold", "italic", "h1", "h2", "h3", "snippet-link"]) # "snippet-link"を追加
# blocks.pyなどでクラスを継承する例
from wagtail.core import blocks
class RichTextBlock(blocks.RichTextBlock):
def __init__(self):
super().__init__(features=[
'h2', 'h3', 'h4', 'bold', 'italic', 'link',
'image', 'ol', 'ul', 'hr', 'embed', 'code',
'snippet-link']) # この行を追加
class Meta:
template = "articles/blocks/richtext_block.html"
icon = "doc-full"
label = "RichText"
テンプレートの設定
リンクをどのように表示するかを設定するテンプレートを作成します。
wagtail-draftail-snippet
では、Snippetとして登録されているモデルと、それに対応する{app_name}/{model_name}_snippet_link.html
という形式のテンプレートを設定すればRichText上でそのsnippetの情報を利用することができるようになります。
例えば、キャンペーンやアフィリエイトなどの情報を管理するads
という名前のDjangoアプリケーションがあるとしましょう。その中で、以下のようにAffiliateLinkという名前のモデルをWagtailのSnippetとして設定します。
# models.py
from django.db import models
from wagtail.admin.edit_handlers import FieldPanel
from wagtail.snippets.models import register_snippet
@register_snippet
class AffiliateLink(models.Model):
"""Affiliate Link"""
snippet_name = models.CharField("Snippet Name", max_length=100)
href = models.CharField(max_length=300)
rel = models.CharField(blank=True, max_length=50)
target = models.CharField(blank=True, max_length=20)
name = models.CharField(blank=True, max_length=50)
panels = [
FieldPanel("snippet_name"),
FieldPanel("href"),
FieldPanel("rel"),
FieldPanel("target"),
FieldPanel("name"),
]
def __str__(self):
return self.snippet_name
class Meta:
verbose_name = "Affiliate Link"
verbose_name_plural = "Affiliate Links"
AffiliateLinkモデルをsnippetとして設定すると、adminから各要素を設定できるようになります。今回の例では、特定のキャンペーンページ用のリンクを設定しています。
新しいsnippetを作成することができたら、これをRichText上で利用できるようにしましょう。wagtail-draftail-snippet
で指定されている形でテンプレートを作成しましょう。
今回はadsアプリケーションのAffiliateLinkモデルをsnippetにしているので、ads/ affiliatelink_snippet_link.html
という名前でテンプレートを作成する必要があります。AffiliateLinkモデルで設定した要素に合わせて、以下のようなテンプレートを作成します。
<a href="{{ object.href }}"
{% if object.name %}name={{ object.name }}{% endif %}
{% if object.rel %}rel="{{ object.rel }}"{% endif %}
{% if object.target %}target={{ object.target }}{% endif %}
>
<!-- 終了タグは書かない -->
このテンプレートでは、AffiliateLinkモデルの各要素から情報を取得し、もしそのパラメータがあればリンクの要素に付け加えています。必要があればAffiliateLinkモデルとテンプレートに要素を追加することでより柔軟な形に変更することも可能です。
ここまでの設定でRichTextからAffiliateLinkのsnippetから簡単にリンクを挿入できるようになりました。プレビュー画面などで確認すると、AffiliateLinkのsnippetから設定したパラメータでリンクが挿入されていることがわかります。