PyramidでSQLAlchemyを使う 〜単純なSELECTをする〜

Pyramidにて、SQLAlchemyを使って単純なSELECT文を実行する方法、ならびに取得した結果の利用方法について確認します。

SELECTするテーブル定義は以下とします。
※Pyramidのプロジェクトを作成したときに、デフォルトで定義されているmodelsを使います。

スクリーンショット 2014-05-17 21.57.22

また、以下のレコードが登録されている、とします。

スクリーンショット 2014-05-17 22.03.59

上記modelsテーブルに対応するSQLAlchemyのモデルは、以下の内容です。
※これもpyramidのプロジェクトを作成したときに自動で作成されるmodels.pyです。

from sqlalchemy import (
    Column,
    Index,
    Integer,
    String
    )
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import (
    scoped_session,
    sessionmaker,
    )
from zope.sqlalchemy import ZopeTransactionExtension

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()

class MyModel(Base):
    __tablename__ = 'models'
    id = Column(Integer, primary_key=True)
    name = Column(String(255))
    value = Column(Integer)

    def __init__(self, name, value):
        self.name = name
        self.value = value

Index('my_index', MyModel.name, unique=True, mysql_length=255)

さて、前準備はここまでにして、実際にSELECTしてみます。
以下のSQLを実行することを目指します。
select * from models;

(1)MyModelを使って検索する方法
以下のメソッドで実行します。
result = DBSession.query(MyModel).all()

query(MyModel)により、SQL文が生成され、all()を実行する事で、
DBに実際に問い合わせをしています。
ログには、SQLAlchemyのフレームワークにより、実行したSQLが出力されています。

SELECT models.id AS models_id, models.name AS models_name, models.value AS models_value 
FROM models

select * from modelsではなく、全カラムが明示的に指定されていますね。
しかも各カラムにはエイリアス付き。
ORMらしい動きです。

戻り値のresultには、取得した結果が配列として返ってきます。
そのため、len(result)にて、取得した件数が分かります。

では、取得した内容にアクセスしてみます。
配列なので、for文で以下のように実行します。

for item in result:
    log.debug('model.id =>' + str(item.id))
    log.debug('model.name =>' + item.name)
    log.debug('model.value =>' + str(item.value))

取得した内容がログが出力されました。
配列の要素はMyModelのインスタンスですかね。プロパティでフィールドの値を取得できます。

(2)SQL文を指定して実行する方法
次に、MyModelを使わずにSQL文を直接記述して実行する方法を確認します。
ORMのフレームワークを使っているのにSQL文直接記述するのは、
ORMの思想と矛盾するかもしれませんが、
実際の開発の現場では、複雑なSQLになるとORMでは、かえって実装が複雑になる場合もあります。
そんな訳で、知っておいた方が良いので、やり方を確認してみます。

以下のメソッドで実行します。

result = DBSession.execute(
     "SELECT * FROM models"
     )

出力されたログによると、以下のSQLが実行されました。

select * from models;

当たり前ですが、指定したとおりに実行されたようです。

では、実行結果はどうでしょうか。
この場合、実は結果は配列ではありません。
ResultProxyクラスのインスタンスが返ってきます。
この場合、取得した件数は以下のように取得します。

cnt = result.rowcount

取得結果は、fetchall()メソッドを使います。

rows = result.fetchall()

結果rowsは配列なので、以下のようにfor文でアクセスしてみます。

rows = result.fetchall()
        
#取得した内容
for row in rows:
    log.debug('model.id =>' + str(row['id']))
    log.debug('model.name =>' + row['name'])
    log.debug('model.value =>' + str(row['value']))

配列の要素はRowProxyのインスタンスのようです。
カラムの値には、カラム名を使ってアクセスできます。
もっと深く調べる必要ありそうですが、今の時点ではここまでで止めておきます。

さて、上記のように、ORMを使ってやり方、SQLを直接指定して使うやり方を
見てきました。
今後も、この2つのやり方を比較しながら検証を進めて行きます。

次回は、Where句で条件指定をしたSELECTを試してみます。