わざわざlinebreaksを無にする不毛なfilter、Djangoさんの話です。

 Django | Built-in template tags and filters | Django documentation
 Django | Custom template tags and filters | Django documentation

 つい先日beautyOfCodeを導入したという記事を書きましたが(例のあれ(仮題)・beautyOfCodeを導入してみた。)、その際に少しだけblogアプリの方にも手を入れなければなりませんでした。

 beautyOfCode(と言うかSytaxHighlighterさん)ではpreタグ内などの特定の条件の改行やスペース入りの文字列をそれっぽく表示するのですけど、このページではデータベースから引っ張りだしたテキストデータをDjangoの標準フィルターであるlinebreaksを通して表示しているので、preタグ内であろうがなかろうが強制的に空行があればpタグを、改行があればbrタグを挟み込んで出力してくれます。ほとんどの場合、そちらの方が都合がいいわけですけど、今回のように中にタグが混ざるような場合には邪魔になる場合もあって、表示が乱れてしまったのですよね。
 こんな風にタグを混ぜるのならデータベースへ保存する時点でかっちりとしたHTMLなどの体をしていなければならないのですけど、今更言うなよ、だってずっと改行コードを変換して出力でやってきたんだもの。です。

 というわけで、せっかくlinebreaksを適用したのに、それらを後から除外するという不毛なfilterを拵えてみましたよ。


import re

from django import template
from django.template.defaultfilters import stringfilter

register = template.Library()

@register.filter(name='remove_linebreaks')
@stringfilter
def remove_linebreaks_using_regex(value, regex):
    for mo in re.finditer(regex, value, re.S):
        tmp = mo.group().replace('<br />', '\n')
        tmp = tmp.replace('<p>', '')
        tmp = tmp.replace('</p>', '')
        value = value.replace(mo.group(), tmp)
    return value

 元の文字列と除外対象部分を抜き出す事ができる正規表現を渡すと、対象部分のみlinebreaksとは逆の処理をして返してくれます。beautyOfCodeさん向けには、“<pre.*?</pre>”みたいな正規表現を渡して対応していますよ。今のところは問題なく。

 んー、それにしてももうちょっと格好良く書きたいところだが、だが、だが。