CherryPy

前回はメソッド=URLをしていただけるように
色々書いてみましたが今回もその延長です。

The CherryPy Documentation
http://www.cherrypy.org/trunk/docs/book/html/index.html

これが一番詳しいです。

が、英語なのでイヤー!な人がいそうなので
少しずつ解説できればなと思います。

翻訳しろよとか切れられそうですが、
そんなに英語能力ないので無理です。

インストール方法から書いた方がいいんですかね?
その辺はできるかなーとむしろTurobGearsインストールすればOKです。

自動的にCherryPyも入れてくれます。

Windowsへのインストールでしたら
稚拙な記事ですがどうぞ

turbogearsグループ - Twisted Mind in TurboGears - TurboGears in Windows
http://turbogears.g.hatena.ne.jp/Voluntas/20060815/p1

今回は@exposeとURI Mappingをやってみようかなと思います。

動作確認ですが

Windows XP
Python 2.4.3
CherryPy 2.2.1
autoimp 1.0.1

  • autoimpを推奨する会-

Python autoimp module
http://oregonstate.edu/~barnesc/autoimp/

で行っております。

まずは何はともあれソースなぞ。

autoimpをインストールするのがイヤな方は
calendarをimportしてください。

from autoimp import *

#import calendar

import cherrypy
from cherrypy import expose

class Root(object):
    
    WEEKDAY = calendar.weekheader(3).split(' ')
    
    @expose
    def index(self):
        pass
 
    def entry(self, year, month, day, title):
        weekday = self.weekday(year, month, day)
        return "%s/%s/%s (%s) title:%s" % (year, month, day, weekday, title)
    entry.exposed = True
        
    def weekday(self, year, month, day):
        return self.WEEKDAY[calendar.weekday(int(year), int(month), int(day))]

cherrypy.root = Root()

if __name__ == '__main__':
    cherrypy.server.start()

前回のをちょろっと変更してみました。

http://localhost:8080/

でまずはHello, world!が見られることを確認してください。

http://localhost:8080/entry/1999/12/24/foo

http://localhost:8080/entry/2005/01/21/bar

http://localhost:8080/entry/1999/07/31/hoge

(これも前回のパクリ)

これで、曜日が無事表示されていればOKです。

@exposeとメソッド名.exposed = Trueは同じ意味だと把握してOKです。
デコレータが実装された時結構この@exposeを使っていたのに
最近この機能を使って説明しているサイトが少ないので
積極的に使ってみています。

TurboGearsでもコレを使っています。

@exposeを付けるとメソッド名=URLが実装されます
付けないと普通のメソッドになります。

@exposeを付けたのは公開されると思って問題ないと思います。

さて次はURI Mappingです。
なんじゃそりゃ?ですが、簡単です。

今まではRootクラスにメソッドをだらだら書いてましたが
やはり分割したいものです。

なのでこれはCherryPy Documentationをそのままパクってしまいます。

管理と検索を作成します。

http://localhost:8080/admin
http://localhost:8080/search

を作成しようというお話です。
普通ならadminとsearchメソッドを作成して終わりですが
それだと管理がしづらいです。

なのでadminはAdminクラスで、searchはSearchクラスでと分けます。

ではソース。

from autoimp import *

import cherrypy
from cherrypy import expose

class Root(object):
    
    WEEKDAY = calendar.weekheader(3).split(' ')
    
    @expose
    def index(self):
        pass
 
    def entry(self, year, month, day, title):
        weekday = self.weekday(year, month, day)
        return "%s/%s/%s (%s) title:%s" % (year, month, day, weekday, title)
    entry.exposed = True
        
    def weekday(self, year, month, day):
        return self.WEEKDAY[calendar.weekday(int(year), int(month), int(day))]

class Admin(object):
    
    @expose
    def index(self):
        return "/admin or /admin/"
    
class Search(object):
    
    @expose
    def index(self):
        return "/admin/search or /admin/search/"

cherrypy.root = Root()
cherrypy.root.admin = Admin()
cherrypy.root.admin.search = Search()

if __name__ == '__main__':
    cherrypy.server.start()

なんか段々長くなってきて申し訳ない…。

返すのは簡単にしました。

URI Mappingですが、

localhostがrootになります。
それにこのURIにはこのクラスをあてておくよーとなるわけです。

/adminにはAdmin()を
/admin/searchにはSearch()を

何はともあれ見てみましょう。

http://localhost:8080/admin

http://localhost:8080/admin/search

どうでしょうか、なんとなーくわかっていただけましたか?
でもここで疑問が出てきますよね。

Root()にadmin作ったらどーなんの?って。
では作ってみましょう、とりあえずやってみるのが一番です。

    @expose
    def admin(self):
        return "Root() admin"

Rootクラスに上記のadminメソッドを追加してみて

http://localhost:8080/admin

を見てみてください、Adminクラスが表示されると思います。
つまりURI Mappingが優先されるのです。

さてURI Mappingのついでに
defaultメソッドも見ていきましょう。

Rootクラスのadminメソッドを消して
Rootクラスにこれを追加しましょう

    @expose  
    def default(self, *args):
        return "Extra path info: %s" % repr(args)

そして以下のURLを見てください。

http://localhost:8080/foo/bar

fooというメソッドは定義していないので
本来ならエラーになるところです。
dafaultメソッドは未定義のものをすべて引き受けてくれるメソッドです。

404エラーを定義しておくといいかもですね。

今日はこんなところで。

次回は

Static content handling
HTTPError
HTTPRedirect

あたりを説明できればいいなぁと。

というかここまでできればほぼなんでもできます。
SQLAlchemyかSQLObjectを混ぜていきたいですね。

最後にまとめのソースを

from autoimp import *

import cherrypy
from cherrypy import expose

class Root(object):
    
    WEEKDAY = calendar.weekheader(3).split(' ')
    
    @expose
    def index(self):
        pass
 
    def entry(self, year, month, day, title):
        weekday = self.weekday(year, month, day)
        return "%s/%s/%s (%s) title:%s" % (year, month, day, weekday, title)
    entry.exposed = True
        
    def weekday(self, year, month, day):
        return self.WEEKDAY[calendar.weekday(int(year), int(month), int(day))]
    
    @expose  
    def default(self, *args):
        return "Extra path info: %s" % repr(args)

class Admin(object):
    
    @expose
    def index(self):
        return "/admin or /admin/"
    
class Search(object):
    
    @expose
    def index(self):
        return "/admin/search or /admin/search/"

cherrypy.root = Root()
cherrypy.root.admin = Admin()
cherrypy.root.admin.search = Search()

if __name__ == '__main__':
    cherrypy.server.start()