文書操作
SQLAlchemyを試す
デフォルトで、TurboGears 1.0ではORMとしてSQLObjectが、テンプレートシステムとしてKidが採用されており、TurboGears 2.0ではORMとしてSQLAlchemyが、テンプレートシステムとしてGenshiが採用される予定です。
SQLObjectとSQLAlchemyにしろ、KidとGenshiにしろ、どちらを使うか・どちらを学習すべきかという議論は後を絶ちませんが、まずはこう理解することが大切なのではないかと思います。
- どちらを選択するのかはケースバイケースなので、一概に、そして明確に、「こちらがよい」とは誰も断言できない
- 重要なのは両者の違いを把握し、自分のスキルや作成するアプリケーションの要件を鑑みながら適切な選択をすること
とはいえ、私のような知識も経験も目的もないようなダメダメ人間には、そもそも違いがよくわからないので大変です。ということで違いを知るという名目でいつものごとく新しいものに飛びついてしまうのです。
ちなみにSQLObjectとKidはTurboGears 2.0でデフォルトではなくなりますが、デフォルトでなくなるというだけでサポートはされます。「TurboGears 2.0は1.0と99%互換になる予定である」、という記述をTurboGearsのMLのどこかで読んだ記憶があります(残りの1%はCherryPy 2→CherryPy 3の問題)。
ActiveRecordとDataMapper
TurboGearsのドキュメントの中にSQLObjectVSSQLAlchemyというものがあります。これによると
The design of SO follows the Active Record pattern, while SA uses the Data Mapper pattern. This makes SA more flexible, but requires more code for simple operations.
ということらしいです。
SQLObjectはActiveRecordで、SQLAlchemyはDataMapperらしいです。ActiveRecord?DataMapper?なんじゃそれ、という感じですが、「OTN Japan - 今だからデータ・アクセスを真剣に考える! 第2回:データアクセスことはじめ(後編)」を見てみると概念化しやすい感じです。
SQLObjectやSQLAlchemyはPythonとデータベースの仲介役となってくれますが、仲介役として何をどのようにしてくれるのかがいろいろと違うようです。
SQLObjectはActiveRecord
SQLObjectを使う場合には自動的に、Modelに定義するPythonクラスがデータベースのテーブルに、Pythonメソッドがデータベースのカラムに対応するため、扱い方が直感的にわかりやすく、自分で決めなければならないこと(設定)も少なくてすみます。
Pythonとデータベースの対応があらかじめ決まっているなどの制約がある反面、わかりやすく設定も少ないというわけですか。しかし既存の決めごとというのは制約とはいっても初心者にはわかりやすくていいですよね。
SQLAlchemyはDataMapper
一方SQLAlchemyを使う場合には、SQLObject(ActiveRecord)のようなPythonとデータベースの対応が決まっていません。自分で何から何までコントロールできるためSQLObjectを利用する場合に比べてやりたいことが実現できるという利点があります。より高度なデータベース操作を行うことができるといってよいのではないでしょうか。
しかし何でもかんでもできてしまう反面、それに対する決めごと(設定)を記述する必要があるわけで、初心者には敷居が高いということになるでしょう。
すなわち
This makes SA more flexible, but requires more code for simple operations. In practice, the Active Record pattern is more appropriate for most web applications.
ということを忘れるべきではないと思います。
SQLAlchemyを試す
わかっちゃいるけどやめられない、というのは病気です。そうです。私は病気なのです。だからSQLAlchemyを試してしまうのです。以下は病気で頭がおかしくなってしまった人の書いたでたらめな文章なので信用してはいけません。
「-s」オプションを使ってSQLAlchemyを利用したプロジェクトを作成する
tg-adminのquickstartでは「-s」オプションを指定するとSQLObjectの代わりにSQLAlchemyを使うようになっています。これにプラスしてリレーションも確認したいのでidentityを使うために「-i」オプションも付けてしまいましょう。
ということでおもむろに
tg-admin quickstart tgbbs -s -i
としてtgbbsという試しのプロジェクトのひな形を作成することにします。しかし今回のミッションはSQLAlchemyを試すということなので、bbsとして完成させる気はさらさらありません。うひ。
ちなみにうちのTurboGearsはPython 2.5なので少しイレギュラーな動きをするかもしれません。「-s -i」以外のオプションは指定していませんので、データベースはsqliteですし、テンプレートはKidです。
identityのモデルはどうなってるのか
肝はもちろんモデルの設定です。とりあえずidentityのモデルがどうなっているのかを見ながらSQLAlchemyの使い方を調べてみることにします。
上記のquickstartで生成されたプロジェクトのmodel.pyを見てみると、すでにidentityのためのモデルが設定されています。ざっと適当に眺めているとだいたい3つの部分から構成されていることがわかります。
まずはテーブルの設定。
以下のような感じでデータベースのテーブルスキーマを設定しているようです。
visits_table = Table('visit', metadata,
Column('visit_key', String(40), primary_key=True),
Column('created', DateTime, nullable=False, default=datetime.now),
Column('expiry', DateTime)
)
最初にメタデータとしてテーブル名を指定、その後各カラムの名前やデータ型などを指定しています。
次にクラスの定義。
以下のような感じでPythonオブジェクトを定義しているようです。利用するメソッドを定義すればOKということでしょうか。
class Visit(object):
"""
A visit to your site
"""
def lookup_visit(cls, visit_key):
return Visit.get(visit_key)
lookup_visit = classmethod(lookup_visit)
そしてマッパーの設定。
コンテクスト上で利用するPythonオブジェクトとテーブルの対応付けをしているっぽいです。
assign_mapper(session.context, Visit, visits_table)
assign_mapperのドキュメントも見ておくとよいかもぉ。
試しに簡単なモデルを作ってみる
リレーションを試してみたいのですが、とりあえず単純なところからいじるほうが安全だということを言い訳にして後回しにします(identity使った意味が…)。
ということで、bbsですから何らかのコメントが投稿されるわけですので超単純なコメントのモデルを作ってみます。
コメントには、idと、タイトルと、本文と、投稿日を設定しましょう。
comments_table = Table('comment', metadata,
Column('comment_id', Integer, primary_key=True),
Column('comment_title', Unicode(255)),
Column('comment_body', Unicode(1024)),
Column('posted', DateTime, nullable=False, default=datetime.now),
)
ちなみに投稿日のカラムは前述のvists_tableの定義から頂戴いたしました。
次にクラスの定義です。まぁ適当にほげほげと。
class Comment(object):
def __init__(self, comment_title, comment_body):
self.comment_title, self.comment_body = comment_title, comment_body
最後にテーブルとPythonクラスをマッピングします。
assign_mapper(session.context, Comment, comments_table)
データを投入してみる
まずはテーブルを生成するために、コマンドプロンプトからtgbbsのディレクトリへ入って
tg-admin sql create
します。
ちなみにdev.cfgにて
sqlalchemy.echo = 1 # デフォルトは0
としてやれば、sqlalchemyのログを出力させることができます。
データを投入するためにshellを起動します。コマンドプロンプトから
tg-admin shell
します。シェルに入ったら、コメントのインスタンスを作成し、データベースに保存します。
c = Comment('Test Comment', 'This is a test.')
c.flush()
うちではIPythonを使って、さらにsqlalchemy.echo = 1しているので以下のような感じになります。
C:\Documents and Settings\nyusuke\My Documents\TurboGears\tgbbs>tg-admin shell
Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit (Intel)]
Type "copyright", "credits" or "license" for more information.
IPython 0.7.3 -- An enhanced Interactive Python.
? -> Introduction to IPython's features.
%magic -> Information about IPython's 'magic' % functions.
help -> Python's own help system.
object? -> Details about 'object'. ?object also works, ?? prints more.
In [1]: c = Comment('Test Comment', 'This is a test.')
In [2]: c.flush()
2007-04-05 01:15:50,467 INFO sqlalchemy.engine.base.Engine.0x..90 BEGIN
2007-04-05 01:15:50,467 sqlalchemy.engine.base.Engine.0x..90 INFO BEGIN
2007-04-05 01:15:50,467 INFO sqlalchemy.engine.base.Engine.0x..90 INSERT INTO co
mment (comment_title, comment_body, comment_posted) VALUES (?, ?, ?)
2007-04-05 01:15:50,467 sqlalchemy.engine.base.Engine.0x..90 INFO INSERT INTO co
mment (comment_title, comment_body, comment_posted) VALUES (?, ?, ?)
2007-04-05 01:15:50,467 INFO sqlalchemy.engine.base.Engine.0x..90 ['Test Comment
', 'This is a test.', '2007-04-05 01:15:50.468000']
2007-04-05 01:15:50,467 sqlalchemy.engine.base.Engine.0x..90 INFO ['Test Comment
', 'This is a test.', '2007-04-05 01:15:50.468000']
2007-04-05 01:15:50,467 INFO sqlalchemy.engine.base.Engine.0x..90 COMMIT
2007-04-05 01:15:50,467 sqlalchemy.engine.base.Engine.0x..90 INFO COMMIT
In [3]:
ここでデータベースの中身を調べるために一度shellを抜けて、コマンドプロンプトから
sqlite3 devdata.sqlite
します。
C:\Documents and Settings\nyusuke\My Documents\TurboGears\tgbbs>sqlite3 devdata.sqlite
SQLite version 3.3.10
Enter ".help" for instructions
sqlite> select * from comment;
1|Test Comment|This is a test.|2007-04-05 01:15:50.468000
sqlite>
わーい、保存されてるみたいですね。
眠たいので寝ます。おやすみなさ~ぃ。
- カテゴリ
-
Turbogears
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://nagosui.org:8080/Nagosui/COREBlog2/trying-sqlalchemy/tbping


