Djangoでテンプレートフィルタを作る

Djangoで「reStructuredText」を使っているのですが、

ユーザー側に

・管理側のテキストエリアで入力された「HTML」をそのまま表示させたい。
・コメント欄(テキストエリア)を「reStructuredText」で書けるようにしたい。
・コメント欄(テキストエリア)に入力された「HTML」は「escape」させたい。

などの問題があります。

なので、

ユーザー側に

・reStructuredTextのみを表示させる。
・reStructuredTextとHTMLをそのまま表示させる。

の2パターンが必要になります。

なのでテンプレートフィルタを作成する事にしました。

※11月10日追記
見づらいので、Wikiに記載しました。

まずテンプレートフィルタの作成方法を

Djangoの和訳ドキュメントに書かれている通りやってみました。

「templatetags」パッケージを適当な「Django」アプリケーションパッケージ内に作ります。
※パッケージは models.py や views.py などと同じ階層にせねばなりません。

なので下記のようになります。

test/
models.py
templatetags/
views.py

のように「templatetags」ディレクトリを作成。
その後に
「templatetags」内にファイルを2つ追加します。

・ __init__.py
・ 自作のタグ/フィルタ定義の入ったファイル

今回は自作のタグ/フィルタ定義の入ったファイルを「rawtext.py」のような名前で作成するので、

・ __init__.py
・ rawtext.py

になります。

「__init__.py」には何も書かなくて良いが、
「rawtext.py」にフィルタ定義を書きます。

今回は「reStructuredText」使うため
/DjangoをインストールしたPATH/django/contrib/markup/templatetags/markup.py
に記述されている

def restructuredtext(value):
try:
from docutils.core import publish_parts
except ImportError:
if settings.DEBUG:
raise template.TemplateSyntaxError, “Error in {% restructuredtext %} filter: The Python docutils library isn’t installed.”
return force_unicode(value)
else:
docutils_settings = getattr(settings, “RESTRUCTUREDTEXT_FILT|~ER_SETTINGS”, {})
parts = publish_parts(source=smart_str(value), writer_name=”html4css1″,settings_overrides=docutils_settings)
return force_unicode(parts[“fragment”])

を使用します。
「rawtext.py」を下記のように記述します。

# vim: fileencoding=utf-8 :

import re
from django.template import Library
from docutils import nodes
from docutils.parsers.rst import directives
from django.conf import settings
from django.utils.encoding import smart_str, force_unicode

register = Library()

@register.filter
def rawtext(value):
def raw_directive(name, arguments,options, content, lineno,
content_offset, block_text, state, state_machine):
return [nodes.raw(”, u’\n’.join(content), format=’html’)]
raw_directive.content = 1
directives.register_directive(‘raw’, raw_directive)

try:
from docutils.core import publish_parts
except ImportError:
if settings.DEBUG:
raise template.TemplateSyntaxError, “Error in {% restructuredtext %} filter: The Python docutils library isn’t installed.”
return force_unicode(value)
else:
docutils_settings = getattr(settings, “RESTRUCTUREDTEXT_FILTER_SETTINGS”, {})
parts = publish_parts(source=smart_str(value), writer_name=”html4css1″, settings_overrides=docutils_settings)
return force_unicode(parts[“fragment”])

まず必要なライブラリなどをimportします。
その時にテンプレートフィルタを作成するのにひつようなのが、

from django.template import Library
register = Library()

上記を記述するのは、

有効なタグライブラリを作るには、 register という名前のモジュールレベル変数に template.Library のインスタンスを入れておく必要があります。このインスタンスには、全てのタグとフィルタが登録されます。

の為です。

次に

Django テンプレート言語で使えるようにするために Library インスタンスに登録する必要があります。
※バージョン 2.4 以上の Python を使っているのなら、 register.filter() デコレータを使えます

なので、

下記も記述します。

@register.filter

ドキュメントに記載されている通り

@register.filter(name=’rawtext’)

でも良いです。
今回は関数名をそのままフィルタ名として使用するので省略しました。

次に実際に作成したテンプレートフィルタを使用します。
下記を使用するテンプレートに記述します。

{% load rawtext %}

フィルタの使用例は下記になります。

{ comment|rawtext }

のようになります。

「reStructuredText」のみを表示する場合は、

{{ comment|restructuredtext }}

よって、

ユーがー側のコメントを表示する部分を

{{ comment|restructuredtext }}

にして、

管理画面でテキストエリア(tipstext)に入力された部分を表示する場合を

{{ tipstext|rawtext }}

と記述します。

入力方法は

「reStructuredText」で入力する場合は、

.. sourcecode:: 言語(javascriptやpythonなどのように)

<input type="text" name="hoge">

「HTML」を入力する場合は、

.. raw::

<input type="text" name="hoge">

になります。

これで2パターン対応する事が出来ました。

今回もnobuさんにヘルプしていただきながら、

色々教えていただきました。

ありがとうございました。

参考サイト
Djangoオンラインドキュメント和訳

投稿者:

kishir

趣味: sk8, ピスト、ターンテーブル、レコード 仕事: Python, Objective-C, PHP, JavaScript

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です