web.py with mod_wsgi (and sqlite3)

最近自分のなかでmod_wsgiが熱いので、 ずいぶん前につくったweb.pyのブログエンジン を web.pyバージョン0.3に対応させ、 さらにデータベースをsqlite3で動かし、 それをmod_wsgiの力で動かすようにしてみました。

web.pyでつくった超シンプルBlog (ver 0.0.3)

Blogのソースは少し込み入っているので、 今回は簡単なサンプルコードでsqlite3とmod_wsgiの設定例を示したいと思います。

web.py with sqlite3

すこし長いですが、まずサンプルを以下に示します(code.py)。 アプリケーションの概要としては、 http://domain/ はindexでさばき http://domain/* はhelloでさばきます。 indexは"Hello web.py"とだけ表示し、helloは ドメインに続く文字列をユーザ名と見立てて、DBの中にユーザ名が存在するかどうか チェックし、存在すれば"already exist"と表示、存在しなければDBに保存し "Nice to meet you"と表示します。

/var/www/app/code.wsgi

import os
import sqlite3
import web

DBPATH = '/var/www/app/hello/hello.sqlite'
TEMPLATE_PATH = '/var/www/templates/'

urls = (
    '/', 'index',
    '/(.*)', 'hello',
)

render = web.template.render(TEMPLATE_PATH)
application = web.application(urls, globals()).wsgifunc()
db = web.database(dbn='sqlite', db=DBPATH)

class hello:
    def GET(self, username):
        users = db.select('hellouser', where="name = '%s'" % username)
        isFound = False
        for u in users:
            if u.name == username:
                isFound = True
        if not isFound:
            db.query("INSERT INTO hellouser (name) VALUES ('%s')" % username)
        return render.hello(username, isFound)

class index:
    def GET(self):
        return "Hello web.py"

if __name__ == '__main__':
    if not os.path.exists(DBPATH):
        d = sqlite3.connect(DBPATH)
        c = d.cursor()
        c.execute("create table hellouser (userid integer primary key autoincrement, \
                   name text)")
    application = web.application(urls, globals())
    application.run()

/var/www/templates/hello.html

$def with (name, isFound)
<html><body>
$if isFound:
    <p>Hello $name</p>
    <p>already exist in database.</p>
$else:
    <p>Hello $name</p>
    <p>Nice to meet you.</p>
</body></html>

standaloneで動かす(CheeryPy)には、

$ /var/www/app
$ python code.py

とします。sqlite3を使うには、パラメータdbn='sqlite'として、dbパラメータに sqliteのDBファイルパスを指定すればOKです。

## MySQLdb or psycopg2 style
#db = web.database(dbn='postgres', user='username', pw='password', db='dbname')
## sqlite3 style
db = web.database(dbn='sqlite', db=DBPATH)

mod_wsgiでの動かし方を次のセクションで。

web.py with mod_wsgi

mod_wsgiの設定方法は webpy.org のドキュメントが少々古い ので、 mod_wsgiのドキュメントを参考にしました。

IntegrationWithWebPy - modwsgi - How to use web.py with mod_wsgi. - Google Code

アプリケーション本体は先ほどのサンプルのままでOKです。

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

上記がmod_wsgiに対応させる唯一の設定です。(以外とあっさりです。)

apache.confのバーチャルホスト等の設定の中にwsgiスクリプトへのエイリアスを 張ってあげると設定完了です。(以下、私の環境での例です。)

$ cd /var/www/app/code.wsgi
$ vim /etc/apache2/sites-available/default
$ chown www-data /var/www/app/hello/hello.sqlite
$ /etc/init.d/apache2 restart
# /etc/apache2/sites-available/default
<VirtualHost *:80>
    WSGIScriptAlias /webpy /var/www/app/code.wsgi
</VirtualHost>

EOF

web.pyはシンプルながら強力なフレームワークです。 小~中規模のWebアプリケーションの作成やパイロットアプリケーションの作成等に 使えるのではないでしょうか。(私もそのような用途で使っています。)

reddit.com の例のように大規模なWebサイトの運用例もあるので、 大規模なアプリケーションにも十分使えると思います。