alchemy scaffold によって生成される初期ファイルは非常に基本的なもの ですが、ほとんどの url dispatch ベースの Pyramid プロジェクト に共通する高レベルパターンの良い方向性を提供します。
このチュートリアルステージのソースコードを以下の場所で閲覧することができます。 http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/basiclayout/.
ディスク上のディレクトリは __init__.py ファイルを含むことによって Python package になることができます。このファイルがたとえ空でも、 Python パッケージとしてディレクトリをマークします。私たちはディレクトリ がパッケージであることを示すマーカーとして、および設定コードを置くために __init__.py を使用します。
tutorial/tutorial/__init__.py を開いてください。 すでに以下の内容が含まれているはずです:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pyramid.config import Configurator from sqlalchemy import engine_from_config from .models import DBSession def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ engine = engine_from_config(settings, 'sqlalchemy.') DBSession.configure(bind=engine) config = Configurator(settings=settings) config.add_static_view('static', 'static', cache_max_age=3600) config.add_route('home', '/') config.scan() return config.make_wsgi_app()
順番に見て行きましょう。 まず、後のコードのためにいくつかのインポートが必要です:
1 2 3 4 from pyramid.config import Configurator from sqlalchemy import engine_from_config from .models import DBSession
__init__.py は main という名前の関数を定義しています。 これは __init__.py の中で定義された main 関数全体です:
1 2 3 4 5 6 7 8 9 10 def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ engine = engine_from_config(settings, 'sqlalchemy.') DBSession.configure(bind=engine) config = Configurator(settings=settings) config.add_static_view('static', 'static', cache_max_age=3600) config.add_route('home', '/') config.scan() return config.make_wsgi_app()
pserve development.ini コマンドを起動すると、上記の main 関数が 実行されます。 main 関数は、いくつかの設定を受け取って WSGI アプリケーションを返します (pserve に関する詳細は Startup を参照してください)。
main 関数は最初に engine_from_config を使用して development.ini ファイルの [app:main] セクション中の sqlalchemy. 接頭辞のついた 設定から SQLAlchemy データベースエンジンを作成します。これは (sqlite:// のような) URI になります:
1 engine = engine_from_config(settings, 'sqlalchemy.')
main はその後、エンジンを渡すことで SQLAlchemy を使って SQL データ ベースを初期化します:
DBSession.configure(bind=engine)
main の次のステップは Configurator オブジェクトを構築することです:
config = Configurator(settings=settings)
settings は **settings 引数として渡された辞書の値を持つ キーワード引数として Configurator に渡されます。 これは .ini ファイルからパースされた設定の辞書になり、これには デプロイ関連の値である pyramid.reload_templates や db_string などが含まれます。
main は 2つの引数、 static (名前) と static (パス) を引数と して pyramid.config.Configurator.add_static_view() を呼び出します。
config.add_static_view('static', 'static', cache_max_age=3600)
これは /static 接頭辞から始まる全ての URL に一致する静的リソースの ビューを登録します (add_static_view への最初の引数によって)。これによって tutorial パッケージの中の static ディレクトリにある静的リソースが、 この場合は http://localhost:6543/static/ 以下を経由して返されるように なります (add_static_view への2番目の引数によって)。この宣言によって、 /static から始まる全ての URL は静的ビューに行かなくてはならない、と いうことを表しています。パスの残りの全ての部分 (例: /static/foo の /foo) は CSS ファイルなどの静的ファイルリソースへのパスを作成するのに使われます。
また、 main は configurator を使用して URL が / の場合に使用される route configuration を pyramid.config.Configurator.add_route() メソッド経由で登録します。
config.add_route('home', '/')
このルートは / に一致する パターン を持っているので、 URL / 、 例えば http://localhost:6543/ を閲覧した場合にマッチします。
main は、次に configurator の scan メソッドを呼び出します。 これは @view_config (また他の特別な) デコレータを探して tutorial パッケージを再帰的に走査します。 @view_config デコレータが見つかったら、 ビュー設定が登録されます。それはアプリケーション URL の 1 つをあるコード にマップすることを可能にするでしょう。
config.scan()
最後に、 main は設定を終えて、 pyramid.config.Configurator.make_wsgi_app() メソッドを使用して WSGI アプリケーションを返します。
return config.make_wsgi_app()
route からそのルートのパターンが一致する時に実行されるコードへ のマッピングは view configuration の登録により行われます。 このアプリケーションでは、各ルートにビュー callable をマッピングするために pyramid.view.view_config() デコレータを使用していて、それによって URL パターンをコードにマッピングします。
tutorial/tutorial/views.py を開いてください。 すでに以下の内容が含まれているはずです:
1 2 3 4 5 6 7 8 9 10 11 from pyramid.view import view_config from .models import ( DBSession, MyModel, ) @view_config(route_name='home', renderer='templates/mytemplate.pt') def my_view(request): one = DBSession.query(MyModel).filter(MyModel.name=='one').first() return {'one':one, 'project':'tutorial'}
ここで重要なのは、 @view_config デコレータがそれがデコレートする関数 (my_view) を以下のような view configuration と関連付けるという ことです:
- route_name (home)
- renderer これはパッケージの templates サブディレクトリに存 在するテンプレートです。
home ビューに関連したパターンがリクエストの間にマッチした場合、 my_view() が実行されるようになります。 my_view() は辞書を返します; レンダラーは辞書中の値に基づいてレスポンスを生成するために templates/mytemplate.pt テンプレートを使用します。
my_view() が request という名前の単一の引数を受け取ることに注意 してください。これは Pyramid view callable の標準的な呼び出し シグネチャです。
__init__.py の中で pyramid.config.Configurator.scan() メソッド (つまり config.scan()) を実行した時のことを覚えていますか? scan メソッドを呼ぶ目的は、アプリケーション内のビュー設定を生成する ために、この @view_config デコレータを見つけて処理することでした。 scan によって処理されなければ、デコレータは実質的に何もしません。 scan によって検知されなければ、 @view_config は不活発です。
SQLAlchemy ベースのアプリケーションの中で、 model オブジェクトは SQL データベースに問い合わせることによって構成されるオブジェクトです。 alchemy scaffold は、モデルを実装するクラスを models.py ファイルに 出力します。
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 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 MyModel(Base): __tablename__ = 'models' id = Column(Integer, primary_key=True) name = Column(Text, unique=True) value = Column(Integer) def __init__(self, name, value): self.name = name self.value = value
それでは詳しく見てみましょう。最初に、この後のコードを動かすために いくつかのインポートが必要です:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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
次に SQLAlchemy の “DBSession” オブジェクトをセットアップします:
1 DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
scoped_session と sessionmaker は SQLAlchemy の標準的なヘルパー です。 scoped_session は、データベース接続にグローバルにアクセスできる ようにします。 sessionmaker はデータベースのセッションオブジェクトを 作成します。システムが自動的にデータベーストランザクションを管理する ことを可能にするために sessionmaker に extension=ZopeTransactionExtension() 拡張オプションを渡しています。 ZopeTransactionExtension を有効にすると、アプリケーションはすべての リクエストの後で自動的にトランザクションのコミットを発行します。ただし、 例外が上げられた場合にはトランザクションは abort します。
また、モデルのベースクラスとして使うために declarative Base オブジェクトを作成する必要があります:
Base = declarative_base()
モデルクラスはこの Base からクラスを継承します。そのため それらを特定のデータベース接続に関連付けることができます。
モデルクラスの簡単な例のため、 MyModel という名前のモデルを定義して います。
1 2 3 4 5 6 7 8 9 class MyModel(Base): __tablename__ = 'models' id = Column(Integer, primary_key=True) name = Column(Text, unique=True) value = Column(Integer) def __init__(self, name, value): self.name = name self.value = value
サンプルモデルの __init__ は 2 つの引数を取ります (name と value)。 これらの値は __init__ 関数自身の中で self.name および self.value として保存されます。 MyModel クラスはまた、 __tablename__ 属性を持っています。これは、このクラスのインスタンス を表すデータを格納するために使用するテーブルを SQLAlchemy に通知します。
アプリケーションに含まれるモデル、ビュー、および初期化コードに関して、 これでおよそすべてです。