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オンラインドキュメント和訳

Python温泉

無事に家に到着してガン寝してました。

いや~結構遠かったな。

そして楽しかったっす。

それぞれみんな共通の話題もあり、

結構みんな感動してたりなんかもして、

良かったっす。

イロイロな人の話を聞いていると、

やっぱり勉強不足だなと。。。

すごい気になったのは「vim」の話とかっすね。

これは人それぞれ違うところがあるんで、

すごくおもしろかったっす。

今回の予定は、

自分の中で作る物をある程度決めていて、

それは完成出来たので良かった。

作ってて問題になった点は

1. newformsでプルダウンを生成した時に
「——-」が自動で入ってしまうので無くす。
2. フィードは必要でしょ!って事で追加しよう。

1番目は、nobuさんが解決してくれました。
ありがとうございました。
これはまとめて、ブログに書かせてもらいます。

2番目はドキュメントを読んでいたのですが、
眠すぎて全然頭に入らなかった。。。
自分の頭がまともな時に読みます。

まだまだDjangoの事やPythonの事がしっかりと解らないので、

ソースを見たり人のを参考にイロイロと試して、

次のPython温泉までには、

他の人の話について行けるようにします。

幹事をしていただいたvoluntasさんありがとうございました。

そして皆さんもお疲れ様でした。

Djangoに興味のある方は是非!

Djangoを体験しよう

Django and TinyMCEを試す

最近風邪を引いていて辛かったので、

家でPCを付けれなかった。。。

今回は、

「Django and TinyMCE」

をやってみたっす。

参考にしたのは、

本家サイトのここっす。

すげぇ~簡単に出来たので、

良かったw

ってかadminテンプレートのオーバーライドにはまった。。。

TinyMCEから

「tinymce_2_1_2.tgz」

を落としてきて、

その中にある

「tiny_mce」

っていうディレクトリを自分の「jsファイルディレクトリ」に置いた。

後は、

同じく「jsファイルディレクトリ」に

「textareas.js」

みたいな名前で、

本家の ここ のソースコードを記述するように書いてあるので、記述して保存。

で、

adminテンプレートで上記2ファイルを読み込む。

今回は編集画面に適用してみたので、

「change_form.html」をオーバーライドする。

{% extends "admin/change_form.html" %}
{% block extrahead %}{{ block.super }}
<script type="text/javascript" src="/static/js/tiny_mce/tiny_mce.js"></script>
<script type="text/javascript" src="/static/js/textarea.js"></script>
{% endblock %}

こんな感じっすね。

で、

画面はこんな感じ

いいかもw

IPythonを使うと幸せになれますね。

最近家でDjangoを勉強中っす。

ってことで、「IPython

以前nobuさんにこれは使いなさいと言われていて、

仕事が忙しかったので

(DjangoってかPythonが全然勉強出来なかったんだけど。。。)

使う機会が無く忘れてた。。。

でも最近は家でちょこちょこいじってるので、

やっと使う機会が出てきた。

nobuさんに聞いてばっかりだったので、

自分で色々と試してみて見る事にしたっす。

本当にいつも丁寧に教えてもらって

ありがとうございま〜す

「IPython」これは便利で幸せになれる。

ueBLOGさんの記事を見て、

初めて知ったのですがモジュールのヘルプやら

色々と出来るみたいですね。

これからはどんどん活用して行こう!

ってか普段は仕事でPHPを使ってるのですが、

こんな機能は追加で開発されないのかな?

仕事で使う分あるとかなり便利なんだけどな。。。