基本的なレイアウト¶
alchemy
scaffold によって生成される初期ファイルは非常に基本的なもの
ですが、ほとんどの url dispatch ベースの Pyramid プロジェクト
に共通する高レベルパターンの良い方向性を提供します。
このチュートリアルステージのソースコードを以下の場所で閲覧することができます。 http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/basiclayout/.
__init__.py
でのアプリケーション設定¶
ディスク上のディレクトリは __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 16 17 18 19 20 from pyramid.config import Configurator from sqlalchemy import engine_from_config from .models import ( DBSession, Base, ) def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ engine = engine_from_config(settings, 'sqlalchemy.') DBSession.configure(bind=engine) Base.metadata.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 5 6 7 from pyramid.config import Configurator from sqlalchemy import engine_from_config from .models import ( DBSession, Base, )
__init__.py
は main
という名前の関数を定義しています。
これは __init__.py
の中で定義された main
関数全体です:
1 2 3 4 5 6 7 8 9 10 11 def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ engine = engine_from_config(settings, 'sqlalchemy.') DBSession.configure(bind=engine) Base.metadata.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 になります:
engine = engine_from_config(settings, 'sqlalchemy.')
main
はその後、 engine を渡すことで SQLAlchemy セッションオブジェクト
を初期化します:
DBSession.configure(bind=engine)
main
は続いて SQLAlchemy の declarative (宣言的) Base
オブジェクトを
初期化します (作成した engine を metadata
オブジェクトの bind
属性に
割り当てます)。これは、 (クラス構文によって宣言的に行う代わりに) 命令的に
行われたテーブル定義が動作するようにします。このアプリケーションの中では
そのようなテーブルを使用しませんが、後で (それもこのチュートリアルのこと
なんか忘れてしまうくらいかなり後になって) そのようなテーブルを追加したなら、
それが動作しないことにずっと悩むことになるでしょう。
Base.metadata.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
メソッド
(pyramid.config.Configurator.scan()
) を呼び出します。
これは @view_config
(また他の特別な) デコレータを探して tutorial
パッケージを再帰的に走査します。 @view_config
デコレータが見つかったら、
ビュー設定が登録されます。それはアプリケーション URL の 1 つをあるコード
にマップすることを可能にするでしょう。
config.scan()
最後に、 main
は設定を終えて、
pyramid.config.Configurator.make_wsgi_app()
メソッドを使用して
WSGI アプリケーションを返します。
return config.make_wsgi_app()
views.py
によるビュー定義¶
route からそのルートのパターンが一致する時に実行されるコードへ
のマッピングは view configuration の登録により行われます。
このアプリケーションでは、各ルートにビュー callable をマッピングするために
pyramid.view.view_config()
デコレータを使用していて、それによって
URL パターンをコードにマッピングします。
tutorial/tutorial/views.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 from pyramid.response import Response from pyramid.view import view_config from sqlalchemy.exc import DBAPIError from .models import ( DBSession, MyModel, ) @view_config(route_name='home', renderer='templates/mytemplate.pt') def my_view(request): try: one = DBSession.query(MyModel).filter(MyModel.name == 'one').first() except DBAPIError: return Response(conn_err_msg, content_type='text/plain', status_int=500) return {'one': one, 'project': 'tutorial'} conn_err_msg = """\ Pyramid is having a problem using your SQL database. The problem might be caused by one of the following things: 1. You may need to run the "initialize_tutorial_db" script to initialize your database tables. Check your virtual environment's "bin" directory for this script and try to run it. 2. Your database server may not be running. Check that the database server referred to by the "sqlalchemy.url" setting in your "development.ini" file is running. After you fix the problem, please restart the Pyramid application to try it again. """
ここで重要なのは、 @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
は不活発です。
scaffold によって作成されたサンプルの my_view()
は、 try:
と
except:
節を使用して、プロジェクトデータベースへのアクセスに問題が
あるかどうかを検出し、代替エラーレスポンスを提供します。そのレスポンスは、
ファイルの最後に示されたテキストを含み、問題を解決するためにユーザが
取ることのできるアクションについて通知するためブラウザに表示されます。
models.py
とコンテンツのモデル¶
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 28 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
オブジェクトをセットアップします:
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 に通知します。
アプリケーションに含まれるモデル、ビュー、および初期化コードに関して、 これでおよそすべてです。