CharFiledにつっこんだテキストを@やハッシュタグに対応するためにカスタムテンプレートフィルターをつくった
models.CharFiledは勝手にテキストノードっぽい感じでつっこんでくれる
だからエスケープとか考えなくていいけれど、その代わり逆にinnerHTML的にあるテキストに対して書き換える動作をしたかった。そのためにはカスタムテンプレートを自作する必要があった。
テンプレートのフィルタとは
{{ text|urlize }}みたいにあるテキストに対してURLを勝手に展開してくれる便利フィルタ。これを自作する。
基本的な構造
@atasatamatara @ dev:~/skz2_proj$ tree . ├── README ├── __init__.py ├── config.py ├── data_skz.db ├── manage.py ├── settings.py ├── skz2 │ ├── __init__.py │ ├── admin.py │ ├── context_processors.py │ ├── models.py │ ├── templatetags │ │ ├── __init__.py │ │ └── cust_filter.py │ ├── tests.py │ ├── tools.py │ ├── urls.py │ └── views.py │ ├── templates │ ├── base.html │ ├── index.html │ └── skz2.html └── urls.py
こんな感じでtemplatetagsを作って、__init__.pyと任意のカスタムフィルター.pyをつくってやる
中身
from django import template from django.utils.html import conditional_escape from django.utils.safestring import mark_safe import re register = template.Library() @register.filter def user_mention(value, autoescape=None): """@で始まるユーザーをリンクにする""" user = re.search(r'@([\w]+)', value) if user: value= re.sub(r'@[\w]+', '<a href=https://twitter.com/#!/' + user.group(1) +'>@'+ user.group(1)+'</a>', value) return mark_safe(value) user_mention.needs_autoescape = True @register.filter def hashtag(value, autoescape=None): """日本語ハッシュタグを含めたハッシュタグをリンクにする""" hashtag = re.search(r'#([\w一-龠ぁ-んァ-ヴー]+)'.decode('utf-8'), value) #こっちのほうがユニコードを扱うときにはいいかもしれない #hashtag = re.search(ur'#([\w一-龠ぁ-んァ-ヴー]+)', value) if hashtag: value= re.sub(r'#([\w一-龠ぁ-んァ-ヴー]+)'.decode('utf-8'), '<a href=https://twitter.com/#!/search/%23' + hashtag.group(1) +'>#' + hashtag.group(1)+'</a>', value) #value= re.sub(ur'#([\w一-龠ぁ-んァ-ヴー]+)', '<a href=https://twitter.com/#!/search/%23' + hashtag.group(1) +'>#' + hashtag.group(1)+'</a>', value) return mark_safe(value) hashtag.needs_autoescape = True
今回は動的にinnerHTML的に書き換えてやる必要があったのでmark_safeをつかってautoescape=None, needs_autoescape=True にしたけれど、そんなに破壊的なことをやらなければもっと単純にできるはず。
追記
mark_safeとかneeds_autoescape = True とかはなんかなくても動いたような……そこらへんは適宜自分で判断してください。
使うとき
ここでハマった。Loadする必要がある
{% load cust_filter %}
あとは普通にフィルターとして使う
{{ obj.text|urlize|user_mention|hashtag }}
以上
知れば簡単。知らないとハマる。それだけのこと。
参考資料
公式日本語訳に全部書いてあった。
テンプレートタグやフィルタを自作する — Django v1.0 documentation
でもハマったのでほかにもいろいろ参考にした。
テンプレート用のカスタムタグやカスタムフィルタをサブディレクトリに分ける - Pyro Memo
フィルタを自作する - もなじろう日記
Django Template自作フィルタ #Pistatium Blog