Hatena::ブログ(Diary)

脱エンタープライズ志向 このページをアンテナに追加 RSSフィード

2009-04-08

web.py&はてな認証APIを始めるにあたり

| 00:40 | web.py&はてな認証APIを始めるにあたり - 脱エンタープライズ志向 を含むブックマーク

昨日の続きということで、とりあえず何か作ってみよーう

web.pyを使ってみよう

導入

まずはweb.pyの導入ということで、Download (web.py)を参考にダウロード。tar.gzをダウンロードして、以下のコマンドでインストール

$sudo python setup.py install

チュートリアル

web.py 0.2 チュートリアル (web.py)を参考に。でも

web.run(urls, globals())

の部分がVer0.3では動かないので、

application = web.application(urls, globals())
application.run()

に変更。

実装はここらが参考になると思う。

ちょっとはまったところはレンダリングの部分で

print render.HTMLファイル名(パラメータ)

ではなくて、

return render.HTMLファイル名(パラメータ)

returnでないと駄目。(そりゃそうか。)

レンダリング

render = web.template.render('templates/')

で指定したディレクトリを探しにいく。例えば以下の階層でサンプルを作ってみる。

webpy_sample/sample.py
webpy_sample/templates/welcome.html
*webpy_sampleは任意のディレクトリ

sample.py
import web
render = web.template.render('templates/')
urls = (
  '/', 'index',
  '', 'index',
)

class index:
  def GET(self):
    # コンソールに出力
    print "Hello, world!"
    # webpy_sample/templates/welcome.htmlに"test"という文字列を渡す
    return render.welcome("test")

web.internalerror = web.debugerror
if __name__ == "__main__":
  # ver0.2とVer0.3で違う。これはVer0.3仕様
  application = web.application(urls, globals())
  application.run()
templates/welcome.html
$def with (param)
<html><body>
<p>
$if param == None:
  <p>parameter is None</p>
$else:
  <p>parameter is $param</p>
</p>
</body></html>

render.welcome("test")で渡した"test"が$paramに入るので、parameter is testと表示される。

では、実際にサーバーを起動して動作を確認。

$python code.py

http://0.0.0.0:8080/がコンソールに出力されるので、ブラウザで確認してみる。

はてな認証API

何かサービスを作るときははてなの認証機能を使おうと考えている。

ということではてな認証API、はじめの一歩 - 結城浩のはてな日記を参考にちょっとやってみる。jsonを使っているが、Mac10.5.6にデフォルトインストールされているPython2.5には組み込まれていないようなので、自力でやる。参考サイトはPythonでJSONを使う方法 - Object Designソースコードダウンロードして、sample.pyと同階層にjson.pyをコピーしてやると動くようになる。

のソースを参考に実際に動かしてみる。

class Auth(object):
    LOGIN_URL = "http://auth.hatena.ne.jp/auth"
    API_URL = "http://auth.hatena.ne.jp/api/auth"
    def __init__(self, api_key, secret):
        self.api_key = api_key
        self.secret = secret

    def uri_to_login(self):
        params = {"api_key": self.api_key}
        params["api_sig"] = self.api_sig(params)
        return "%s?%s" % (self.LOGIN_URL,
                          "&".join(["%s=%s" % t for t in params.items()]))

    def api_sig(self, params):
        import md5
        m = md5.new(self.secret)
        for k, v in sorted(params.items()):
            m.update(k)
            m.update(v)
        return m.hexdigest()

    def _get_auth_as_json(self, cert):
        import json
        import urllib2
        params = {"api_key": self.api_key, "cert": cert}
        params["api_sig"] = self.api_sig(params)
        url = "%s.json?%s" % (self.API_URL, 
                              "&".join(["%s=%s" % t for t in params.items()]))
        return json.read(urllib2.urlopen(url).read())

    def login(self, cert):
        auth = self._get_auth_as_json(cert)
        if auth["has_error"]:
            raise ValueError(auth["error"]["message"])
        return Storage(auth["user"])

class Storage(dict):
    """see web.py"""
    def __getattr__(self, k): 
        if self.has_key(k): return self[k]
        raise AttributeError, repr(k)
    def __setattr__(self, k, v): self[k] = v
    def __repr__(self): return '<Storage '+dict.__repr__(self)+'>'

if __name__ == '__main__':
    # http://auth.hatena.ne.jp/hatenaアカウントで取得したAPIキーと秘密鍵が表示される
    a = Auth(APIキー, 秘密鍵)

    #-1- 引数は特になし
  #print例)http://auth.hatena.ne.jp/auth?api_sig=13123213321321321api_key=fdsafdafasdafdffdfadsfdsf
  print a.uri_to_login()

    #-2- -1-でprintされたURLにアクセスするとhttp://サイトURL?cert=9c3620b222537e86にリダイレクトされるので
  #cert=の値を渡す。ここでは9c3620b222537e86
    #print例)<Storage {'thumbnail_url': 'ここにURL', 'image_url': 'ここにURL', 'name': 'ニックネーム'}>
    print a.login('9c3620b222537e86')

とりあえずログインの認証はできそうだ。

ちなみに-1-と-2-は同時にはcertがいるので、printできない。

ちょっと追記

テンプレート内で繰り返し処理をするときのメモ。forやifがそのまま使えるよう。

web.pyのテンプレート機能を使ってみるぞなもし - HDEラボ