モブ沢工房

プログラミングとかLinux関連(特にOSSのグラフィックツール関連)とかレトロゲームとか3Dプリンタやら日曜大工等、色々。

python-jinja2について

この記事はfc2から引っ越した記事です

さて、今回テンプレートを1から作るにあたって一番役に立ったのは…
python-jinja2でありました。あと、less.jsもすごく役に立ちましたが、ちょっとこれは柔軟性に乏しい面もあったりして…
あとtwitter bootstrap3も大変役に立っております。残念ながらフォントがfc2ブログにアップロードできない(対応していないファイル形式といわれる)ので、bootstrap3のウリであるグリフアイコンが使えないのですが…

ともかくそのpython-jinja2。これ自体がテンプレートエンジンなのです。
HTMLと擬似命令で書かれたテンプレート(大抵はファイル)をレンダリングするライブラリというところです。

この擬似命令がまた、if文からset文(変数定義・操作)、include文(現在のコンテキストで他のテンプレートファイルをその場にレンダリングする)やらfor文など各種取り揃えられており、しかもその中ではレンダリング時にpythonから渡されたオブジェクトを参照できるのです。

長くなるので一部分だけ抜粋します〜

当初はテンプレートのinclude文も使ってなかったのですが、その後include文も使うようになったりと試行錯誤の結果、やり方が混合しており、ちょっと変な書き方かもですが、参考までに。

import os
from jinja2 import Environment,FileSystemLoader

def main():
env=Environment(loader=FileSystemLoader(os.getcwd()),trim_blocks=True)
default_arg_dict={
'comment_button_color' : 'default',
'usertag_color' : 'info',
'category_color' : 'primary',
}

default_arg_dict['trackback_button_color']=default_arg_dict['comment_button_color']

ta=env.get_template('toppage_article.template')
arg=dict(default_arg_dict)
arg['pagetype']="TOPPAGE"
toppage_article=ta.render( arg ) # toppage_articleにレンダリングされたHTML(fc2テンプレート混じり)が。



そして、jinjaテンプレート(toppage_article.template)の側はこんな感じです


<div class="thumbnail  entire_article">
{% include 'entry_header.template' %}
<div class="media article_body">
<a class="pull-left" href="#">
<%topentry_image_w300>
</a>
<div class="media-body">
<%topentry_discription>
<p></p>
<p class="text-center">
{% if pagetype=="TOPPAGE" %}
<a class="btn btn-success btn-small" href="<%topentry_link>">続きを読む</a>
{% else %}
<a class="btn btn-warning btn-small" href="<%topentry_link>">記事に戻る</a>
{% endif %}
</p>
</div>
</div>
</div>




地味に {% include 〜 %}を使っております。
最終的に複数の部分テンプレートのレンダリング結果を組み合わせて、最終出力のjinjaテンプレートにぶちこむという方法です。
includeを使ったほうがいいのか、このようにpythonコードである程度操作したほうがいいのか。
気分次第というか、ほとんどどちらでもOKという感じです。

この恐ろしいまでの柔軟性は凄い

こうして見比べると、cssのほうのlessはなんというか柔軟性に乏しい気がするというか…
いやまぁ、それなりに使えるツールではあるのですが。
fc2テンプレートのシステムがjinja2を使ってたらすごい楽なんですがね〜。まぁセキュリティ的に無理でしょうか…



なお、こうやってfc2テンプレートをつくりだしても、コピペするのが面倒ですよね?
ファイルに出力したりすると、そのたびにエディタで開きなおして全選択してCTRL+Cして…なんて、面倒で寝てしまいそうです
そこでおいらは作業はターミナルエミュレータ上で行い、pythonスクリプトで最終出力はprint(output.encode('utf-8'))して標準出力に出してしまいます。
そしてXWindowのxselコマンドと組み合わせ…

make_fc2template.py | xsel -ib

として、テンプレート生成と同時にクリップボードに送り込むわけですね。
そしてブラウザのfc2のテンプレート入力欄で全選択してCTRL+Vで貼り付けると。
かなり楽になるわけです。fc2側になんか登録用APIでもあればもっと楽になりそうですけどね…あるのかな〜

しかしおいらの場合、これによって何をしているのかというと、jinja2テンプレートエンジンでfc2テンプレートを作るという、中々意味のわかりづらい行為にw

最も苦労したのはコメント欄でした。
fc2のテンプレートでは、ddとかdtだとかのタグに囲まれてごちゃごちゃして良くわからない物体が、普通のコメント欄とコメント編集欄の2つあるのです。
それも似ているようで微妙に違うという…
これもjinja2ならば、if文を駆使してそれなりに簡単に編集できるのですね。そして一旦編集してテンプレートを作ってしまえば、後はサクサクです。

公式テンプレートからコピってきて必死で書き換え、共通点を探しだしてif文などで状況に応じて細かい差異だけ書き換えるというものにしました。さらにbootstrapのフォーム関連クラスで統一して見栄えをbootstrap的に変更しました。

次に考えているのはjavascriptを使っての「トップページで最初のエントリだけはフルサイズ表示し、残りは縮小版を表示する」というものですが…

いや、意味はありません。ただの自己満足ですwていうか、むやみに遅くなりそうですなぁ…まぁ、やってみることが一番大事ってばっちゃが言ってた(嘘

っていうかあっさりできてしまいました。しかし実際にやってみると意味のなさに脱力。javascriptが動かない環境では縮小版とフルサイズ版の両方が出てしまうというところが情けないのですが、まぁ深く考えないということで…

え〜、トップ画面におけるフルサイズ版は常にスタイルをdisplay:none;にして、javascriptが動かない環境では縮小版だけ表示させるという方法にしました。javascriptが動く場合は最初の記事だけdisplay:block;に変更するというわけです。

さて、今回テンプレートを1から作るにあたって一番役に立ったのは…
python-jinja2でありました。あと、less.jsもすごく役に立ちましたが、ちょっとこれは柔軟性に乏しい面もあったりして…
あとtwitter bootstrap3も大変役に立っております。残念ながらフォントがfc2ブログにアップロードできない(対応していないファイル形式といわれる)ので、bootstrap3のウリであるグリフアイコンが使えないのですが…

ともかくそのpython-jinja2。これ自体がテンプレートエンジンなのです。
HTMLと擬似命令で書かれたテンプレート(大抵はファイル)をレンダリングするライブラリというところです。

この擬似命令がまた、if文からset文(変数定義・操作)、include文(現在のコンテキストで他のテンプレートファイルをその場にレンダリングする)やらfor文など各種取り揃えられており、しかもその中ではレンダリング時にpythonから渡されたオブジェクトを参照できるのです。

長くなるので一部分だけ抜粋します〜

当初はテンプレートのinclude文も使ってなかったのですが、その後include文も使うようになったりと試行錯誤の結果、やり方が混合しており、ちょっと変な書き方かもですが、参考までに。

import os
from jinja2 import Environment,FileSystemLoader

def main():
env=Environment(loader=FileSystemLoader(os.getcwd()),trim_blocks=True)
default_arg_dict={
'comment_button_color' : 'default',
'usertag_color' : 'info',
'category_color' : 'primary',
}

default_arg_dict['trackback_button_color']=default_arg_dict['comment_button_color']

ta=env.get_template('toppage_article.template')
arg=dict(default_arg_dict)
arg['pagetype']="TOPPAGE"
toppage_article=ta.render( arg ) # toppage_articleにレンダリングされたHTML(fc2テンプレート混じり)が。



そして、jinjaテンプレート(toppage_article.template)の側はこんな感じです


<div class="thumbnail  entire_article">
{% include 'entry_header.template' %}
<div class="media article_body">
<a class="pull-left" href="#">
<%topentry_image_w300>
</a>
<div class="media-body">
<%topentry_discription>
<p></p>
<p class="text-center">
{% if pagetype=="TOPPAGE" %}
<a class="btn btn-success btn-small" href="<%topentry_link>">続きを読む</a>
{% else %}
<a class="btn btn-warning btn-small" href="<%topentry_link>">記事に戻る</a>
{% endif %}
</p>
</div>
</div>
</div>




地味に {% include 〜 %}を使っております。
最終的に複数の部分テンプレートのレンダリング結果を組み合わせて、最終出力のjinjaテンプレートにぶちこむという方法です。
includeを使ったほうがいいのか、このようにpythonコードである程度操作したほうがいいのか。
気分次第というか、ほとんどどちらでもOKという感じです。

この恐ろしいまでの柔軟性は凄い

こうして見比べると、cssのほうのlessはなんというか柔軟性に乏しい気がするというか…
いやまぁ、それなりに使えるツールではあるのですが。
fc2テンプレートのシステムがjinja2を使ってたらすごい楽なんですがね〜。まぁセキュリティ的に無理でしょうか…



なお、こうやってfc2テンプレートをつくりだしても、コピペするのが面倒ですよね?
ファイルに出力したりすると、そのたびにエディタで開きなおして全選択してCTRL+Cして…なんて、面倒で寝てしまいそうです
そこでおいらは作業はターミナルエミュレータ上で行い、pythonスクリプトで最終出力はprint(output.encode('utf-8'))して標準出力に出してしまいます。
そしてXWindowのxselコマンドと組み合わせ…

make_fc2template.py | xsel -ib

として、テンプレート生成と同時にクリップボードに送り込むわけですね。
そしてブラウザのfc2のテンプレート入力欄で全選択してCTRL+Vで貼り付けると。
かなり楽になるわけです。fc2側になんか登録用APIでもあればもっと楽になりそうですけどね…あるのかな〜

しかしおいらの場合、これによって何をしているのかというと、jinja2テンプレートエンジンでfc2テンプレートを作るという、中々意味のわかりづらい行為にw

最も苦労したのはコメント欄でした。
fc2のテンプレートでは、ddとかdtだとかのタグに囲まれてごちゃごちゃして良くわからない物体が、普通のコメント欄とコメント編集欄の2つあるのです。
それも似ているようで微妙に違うという…
これもjinja2ならば、if文を駆使してそれなりに簡単に編集できるのですね。そして一旦編集してテンプレートを作ってしまえば、後はサクサクです。

公式テンプレートからコピってきて必死で書き換え、共通点を探しだしてif文などで状況に応じて細かい差異だけ書き換えるというものにしました。さらにbootstrapのフォーム関連クラスで統一して見栄えをbootstrap的に変更しました。

次に考えているのはjavascriptを使っての「トップページで最初のエントリだけはフルサイズ表示し、残りは縮小版を表示する」というものですが…

いや、意味はありません。ただの自己満足ですwていうか、むやみに遅くなりそうですなぁ…まぁ、やってみることが一番大事ってばっちゃが言ってた(嘘

っていうかあっさりできてしまいました。しかし実際にやってみると意味のなさに脱力。javascriptが動かない環境では縮小版とフルサイズ版の両方が出てしまうというところが情けないのですが、まぁ深く考えないということで…

え〜、トップ画面におけるフルサイズ版は常にスタイルをdisplay:none;にして、javascriptが動かない環境では縮小版だけ表示させるという方法にしました。javascriptが動く場合は最初の記事だけdisplay:block;に変更するというわけです。