ドメインモデルを定義する

pcreate から生成したアプリケーションに対して最初に行う変更は、 wiki ページ を表す domain model のコンストラクタを定義することです。これを models.py ファイルの中で行います。

このチュートリアルステージのソースコードを以下の場所で閲覧することができます。 http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/models/.

models.py を編集する

Note

models.py というファイル名には特別な 意味はありません。プロジェクトはそのコードベース全体で任意の名前の ファイル中に多くのモデルを持つことができます。モデルを実装するファイルは 多くの場合 model というファイル名を持っています (もしくは models という名前のアプリケーションパッケージの中の Python サブ パッケージに存在しています) が、これは単なる慣習です。

tutorial/tutorial/models.py ファイルを開き、以下のように編集してください:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from sqlalchemy import (
    Column,
    Integer,
    Text,
    )

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 Page(Base):
    """ The SQLAlchemy declarative model class for a Page object. """
    __tablename__ = 'pages'
    id = Column(Integer, primary_key=True)
    name = Column(Text, unique=True)
    data = Column(Text)

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

(ハイライトされた行は変更が必要な箇所です)

初めにしたことは、生成された models.py ファイルから MyModel クラスを削除することです。 MyModel クラスは単なるサンプルで、 使うことはありません。

それから、 Page クラスを追加しました。これは SQLAlchemy アプリケーション なので、このクラスは sqlalchemy.ext.declarative.declarative_base のインスタンスから 継承します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Page(Base):
    """ The SQLAlchemy declarative model class for a Page object. """
    __tablename__ = 'pages'
    id = Column(Integer, primary_key=True)
    name = Column(Text, unique=True)
    data = Column(Text)

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

ご覧の通り、 Page クラスはクラス属性 __tablename__ を持っていて、 その値は文字列 'pages' に等しいです。これが意味するのは、 SQLAlchemy が wiki データを pages という名前の SQL テーブルに保存 するということです。 Page クラスはまた、 id, name, data という 名前のクラス属性を持っています (全て sqlalchemy.Column の インスタンスです)。これらは pages テーブルのカラムにマップされます。 id 属性はテーブルのプライマリキーになります。 name 属性はテキスト 属性で、各値はカラム内で一意である必要があります。 data 属性は 各ページの本体を保持するテキスト属性です。

scripts/initializedb.py を変更する

このファイルの詳細はまだ見ていませんが、 tutorial パッケージの scripts ディレクトリ内に initializedb.py という名前のファイルが あります。このファイルに含まれるコードは、 initialize_tutorial_db コマンドを実行したときに常に実行されます (このチュートリアルのインストール ステップで行ったように)。

モデルを変更したので、 initializedb.py スクリプトに変更を加える必要が あります。特に、 MyModel のインポートを Page のインポートに置き換え ます。また、 MyModel ではなく Page を作成し、かつ DBSession にそれを加えるためにスクリプトの最終行を変更します。

tutorial/tutorial/scripts/initializedb.py ファイルを開き、以下のように 編集してください:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import os
import sys
import transaction

from sqlalchemy import engine_from_config

from pyramid.paster import (
    get_appsettings,
    setup_logging,
    )

from ..models import (
    DBSession,
    Page,
    Base,
    )


def usage(argv):
    cmd = os.path.basename(argv[0])
    print('usage: %s <config_uri>\n'
          '(example: "%s development.ini")' % (cmd, cmd))
    sys.exit(1)


def main(argv=sys.argv):
    if len(argv) != 2:
        usage(argv)
    config_uri = argv[1]
    setup_logging(config_uri)
    settings = get_appsettings(config_uri)
    engine = engine_from_config(settings, 'sqlalchemy.')
    DBSession.configure(bind=engine)
    Base.metadata.create_all(engine)
    with transaction.manager:
        model = Page('FrontPage', 'This is the front page')
        DBSession.add(model)

(ハイライトされた行は変更が必要な箇所です)

データベースの再初期化

モデルが変わったので、データベースを再初期化するために、 initialize_tutorial_db コマンドを再実行して models.py ファイルと initializedb.py ファイルの両方に加えた変更をピックアップする必要があります。 tutorial プロジェクトのルートディレクトリで次のコマンドを実行します。

UNIX の場合:

$ ../bin/initialize_tutorial_db development.ini

Windows の場合:

c:\pyramidtut\tutorial> ..\Scripts\initialize_tutorial_db development.ini

成功すると以下のような出力が行われます:

2011-11-27 01:22:45,277 INFO  [sqlalchemy.engine.base.Engine][MainThread]
                              PRAGMA table_info("pages")
2011-11-27 01:22:45,277 INFO  [sqlalchemy.engine.base.Engine][MainThread] ()
2011-11-27 01:22:45,277 INFO  [sqlalchemy.engine.base.Engine][MainThread]
CREATE TABLE pages (
      id INTEGER NOT NULL,
      name TEXT,
      data TEXT,
      PRIMARY KEY (id),
      UNIQUE (name)
)


2011-11-27 01:22:45,278 INFO  [sqlalchemy.engine.base.Engine][MainThread] ()
2011-11-27 01:22:45,397 INFO  [sqlalchemy.engine.base.Engine][MainThread]
                              COMMIT
2011-11-27 01:22:45,400 INFO  [sqlalchemy.engine.base.Engine][MainThread]
                              BEGIN (implicit)
2011-11-27 01:22:45,401 INFO  [sqlalchemy.engine.base.Engine][MainThread]
                              INSERT INTO pages (name, data) VALUES (?, ?)
2011-11-27 01:22:45,401 INFO  [sqlalchemy.engine.base.Engine][MainThread]
                              ('FrontPage', 'This is the front page')
2011-11-27 01:22:45,402 INFO  [sqlalchemy.engine.base.Engine][MainThread]
                              COMMIT

ブラウザでアプリケーションを表示する

できません。この時点ではシステムは “実行不可能な” 状態です。次の章で ビュー関連のファイルを変更すればアプリケーションが正常に起動するように なります。もしアプリケーションを起動しようとすると (アプリケーションの起動 参照)、コンソール上にPython トレースバックが表示されて終了することになるでしょう。トレースバックの 最後は以下のような例外になります:

ImportError: cannot import name MyModel

これはまた、テストを実行しようとした場合にも起こります。