Plone4での外部メソッド(External Method)
- コンテンツ
Plone Advent Calender 2011 (20日目)
Advent Calender 2011も残り数日です。皆さん興味深い記事を書かれていて勉強になります。
安田さん(@zenich 19日目記事)に続き、私の担当分としては最後の20日目の記事は外部メソッドについて書いてみます。
外部メソッド(External Method)とは?
ZMIで使用できるPython Scriptは制限されたpythonなので、reパッケージやurllibパッケージ、dir等おなじみの事が色々とできません。この制限は、viewに近いところで複雑なロジックをできるだけ書くべきじゃないという設計思想やセキュリティの観点から妥当な制限だと思います。(正規表現ぐらいは使いたいなぁとたまに思う。)
Python Scriptの制限を超えた事をやりたくなった時はファイルベースのpythonを使用する必要があります。ファイルベースのpythonには大きく分けて「パッケージ開発」と「外部メソッド(External Method)」がありますが、今回は外部メソッドにフォーカスをあてたいと思います。
外部メソッドは、Ploneインスタンスディレクトリ直下のExtensionsというディレクトリに通常のpython scriptファイルを配置し、ZMIで作成したExternal Methodとひもづける事でPageTemplateやPythonScript等から使用可能になります。使用方法はお手軽ですが、pythonの機能が全て使えるので適切な場面で使用するととてもパワフルに機能します。
Extensions/utils.py# coding:utf8 def getData(): return 'data ok'
ZMIで外部メソッド作成(Module Nameはファイル名、Function Nameはメソッド名と一致させます。)
PageTemplateでの使用例(External MethodのIdで呼べます。)
python:context.utils_getData()
Plone2.5時代には、PloneインスタンスディレクトリにExtensionsディレクトリが最初から存在するので迷う事はなかったのですが、Plone4を含めたbuildout環境においてはExtensionsディレクトリが存在しません。
parts/instance/にExtensionsディレクトリを作成すればbuildout以前と同じように外部メソッドを使用できますが、parts/README.txtには以下記述があります。
WARNING: The contents of the parts directory are managed by buildout. Do not make changes here; they will be lost when you next run buildout. To control the parts, edit buildout.cfg and run bin/buildout.
つまり「このディレクトリに変更を加えてもbuildout時に消えちゃうよ。」との事なので、直接ディレクトリを作成するはまずそうです。buildout実行する都度、手動でディレクトリを再作成すれば動作はしますが、README.txtに書かれた流儀に反しますし、メンドクサイです。
buildout実行すると常にparts以下が再作成されるわけではないです。(どういう時に再作成されるのかが理解できてないです。)
buildout環境でのExternal Methodに関する情報を探しましたが私は見つける事はできませんでした。(ご存知の方教えてください) どこかには情報があるのだとは思いますが、情報の少なさから鑑みて今後は外部メソッドを使用するのは止めてパッケージ開発しましょうね、という流れなのだと思います。
ソース管理の観点からもそれはその通りなのですが、ploneを再起動せずに試行錯誤が可能な外部メソッドのスピード感はやはり捨てきれません。
そこで今回は、buildout環境で外部メソッドを使用する際のコツをご紹介したいと思います。
buildout環境で外部メソッドを使う
parts/README.txtを良く読むとparts以下には何もしてはならないと言っているわけではなく、parts/以下に何かをしたい時は直接やるのではなくて、buildout.cfgに何かを書いてねという事ですので言われた通りにしてみます。
parts/以下がbuildoutにより再作成されるタイミングでparts/instance/Extensions/以下にスクリプトファイルが参照できる状態になればよいので、実際のスクリプトファイルをparts以下以外の場所に配置して、シンボリックリンクする方法をとります。
具体的には、buildout.cfgに以下記述を追加します。
parts = ... externalmethod [externalmethod] recipe = iw.recipe.cmd on_install = true cmds = ln -s ${buildout:directory}/src/Extensions ${instance:location}/Extensions
- recipe : iw.recipe.cmdはbuildoutの任意のタイミング(on_install,on_update)で指定されたコマンドを実行してくれます。
- on_install : trueにするとparts以下が再作成されるタイミングでコマンドを実行してくれます。
- cmds : 実行するshellコマンドを記述します(改行とインデントで複数コマンド記述可能)。今回はsrc/に配置したExtensionsディレクトリにシンボリックリンクします。
パッケージで外部メソッドと同じような事をするには?
上述の方法でbuildout環境においても外部メソッドが使用できることはわかりましたが、本来はやはりパッケージでの開発が推奨されます。 ということで、次回はパッケージで外部メソッドと同じような事をする方法について書いてみたいと思います。
Advent Calender21日目は、以前からとても参考にさせていただいているサイト「ngi644の日記」を運営されている永井さん(@rengi644)にお願いいたします。