Symfoware

Symfowareについての考察blog

PythonフレームワークPyramid 1.5チュートリアル SQLAlchemy

Pyramidのチュートリアルを動かしてみています。
PythonフレームワークPyramid 1.5のチュートリアル(pcreate)

Pyramid Tutorial for PyCon JP Sprint 1.0 documentation
こちらのチュートリアルを参考に進めていきます。



SQLAlchemy, sqlahelper



SQLAlchemyを使用するために必要なライブラリをインストールします。


# easy_install sqlalchemy pyramid_tm sqlahelper




チュートリアルはデータベースにsqliteを使用していますが、
せっかくなのでPostgreSQLを使用してみることにしました。

PostgreSQLに接続するために必要なライブラリをインストールします。


# easy_install psycopg2




development.iniへデータベースへの接続情報を追記します。


[app:main]
use = egg:bankaccount

pyramid.reload_templates = true
pyramid.debug_authorization = false
pyramid.debug_notfound = false
pyramid.debug_routematch = false
pyramid.default_locale_name = en
pyramid.includes =
    pyramid_debugtoolbar

# この行を追加
sqlalchemy.url = postgresql+psycopg2://pgadmin:password@localhost:5432/sample





1セッションごとのトランザクションを管理してくれるpyramid_tmを有効に。
development.iniに記載したデータベースへの接続情報を読み込んで、
プログラム中で使用できるようにします。

pcreateコマンドで生成したひな形ディレクトリの中にある
bankaccount/bankaccount/__init__.py
このファイルに設定を追記します。


  1. # -*- coding:utf-8 -*-
  2. from pyramid.config import Configurator
  3. #以下の2行を追加
  4. import sqlahelper
  5. from sqlalchemy import engine_from_config
  6. def main(global_config, **settings):
  7.     """ This function returns a Pyramid WSGI application.
  8.     """
  9.     config = Configurator(settings=settings)
  10.     config.include('pyramid_chameleon')
  11.     # pyramid_tmの読み込みを追加
  12.     config.include('pyramid_tm')
  13.     config.add_static_view('static', 'static', cache_max_age=3600)
  14.     config.add_route('home', '/')
  15.     config.scan()
  16.     
  17.     # sqlalchemyを有効に
  18.     engine = engine_from_config(settings)
  19.     sqlahelper.add_engine(engine)
  20.     
  21.     return config.make_wsgi_app()





これでSQLAlchemyを使う準備が出来ました。





モデルの定義



データベースのテーブルの定義を作成します。
__init__.pyファイルと同じ階層に、models.pyを作成します。

id,name,balance(預金額)の3つのフィールドを持つbankaccountsテーブルの定義です。

・models.py


  1. # -*- coding:utf-8 -*-
  2. import sqlahelper
  3. import sqlalchemy as sa
  4. Base = sqlahelper.get_base()
  5. DBSession = sqlahelper.get_session()
  6. class NotEnoughFunds(Exception):
  7.     pass
  8. class BankAccount(Base):
  9.     __tablename__ = 'bankaccounts'
  10.     id = sa.Column(sa.Integer, primary_key=True)
  11.     name = sa.Column(sa.Unicode(255), unique=True)
  12.     balance = sa.Column(sa.Integer, default=0)
  13.     def __init__(self, name):
  14.         super(BankAccount, self).__init__(name=name, balance=0)
  15.     def deposit(self, amount):
  16.         self.balance += amount
  17.     def withdraw(self, amount):
  18.         if self.balance - amount < 0:
  19.             raise NotEnoughFunds
  20.         self.balance -= amount






作成したmodels.pyをロードするために、resources.pyを作成します。

・resources.py


  1. # -*- coding:utf-8 -*-
  2. from sqlalchemy.orm.exc import NoResultFound
  3. from . import models
  4. class Root(object):
  5.     def __init__(self, request):
  6.         self.request = request
  7.     def get_bankaccount(self):
  8.         try:
  9.             return models.DBSession.query(models.BankAccount).filter_by(name=u'default').one()
  10.         except NoResultFound:
  11.             return None







ビューとテンプレート



・home - BankAccountオブジェクトの表示
・deposit - 金額を受け取って、 BankAccount オブジェクトの deposit メソッドを実行
・withdraw - 金額を受け取って、 BankAccount オブジェクトの withdraw メソッドを実行

という3つのビュー(URL)を作成します。

pcreateで生成されたviews.pyを編集します。

・views.py


  1. # -*- coding:utf-8 -*-
  2. from pyramid.view import view_config
  3. from pyramid.httpexceptions import HTTPFound
  4. from models import NotEnoughFunds
  5. @view_config(route_name='home', renderer='templates/index.pt')
  6. def home(request):
  7.     bankaccount = request.context.get_bankaccount()
  8.     return dict(bankaccount=bankaccount)
  9. @view_config(route_name='deposit', renderer='templates/index.pt')
  10. def deposit(request):
  11.     bankaccount = request.context.get_bankaccount()
  12.     bankaccount.deposit(int(request.params['amount']))
  13.     return HTTPFound(location=request.route_url('home'))
  14. @view_config(route_name='withdraw', renderer='templates/index.pt')
  15. def withdraw(request):
  16.     bankaccount = request.context.get_bankaccount()
  17.     try:
  18.         bankaccount.withdraw(int(request.params['amount']))
  19.     except NotEnoughFunds:
  20.         request.session.flash("you don't have too much money.")
  21.     return HTTPFound(location=request.route_url('home'))





templatesディレクトリに画面表示用の「index.pt」を作成。
表示用のhtmlを記載します。

・index.pt


  1. <!DOCTYPE html>
  2. <html lang="${request.locale_name}">
  3. <head>
  4.     <meta charset="utf-8">
  5.     <title>sample</title>
  6. </head>
  7. <body>
  8.     <div tal:condition="request.session.peek_flash()">
  9.      <ul tal:repeat="m request.session.pop_flash()">
  10.         <li tal:content="m"></li>
  11.      </ul>
  12.     </div>
  13.     <p>Balance: ${bankaccount.balance}</p>
  14.     <form action="${request.route_url('deposit')}" method="post">
  15.      <fieldset>
  16.         <legend>Despsit</legend>
  17.         <input name="amount">
  18.         <input type="submit">
  19.      </fieldset>
  20.     </form>
  21.     <form action="${request.route_url('withdraw')}" method="post">
  22.      <fieldset>
  23.         <legend>Withdraw</legend>
  24.         <input name="amount">
  25.         <input type="submit">
  26.      </fieldset>
  27.     </form>
  28. </body>
  29. </html>





これで準備は整いました。
__init__.pyを編集して、各種初期化処理を記載します。
※実はこのへんはよく理解できていません。


  1. # -*- coding:utf-8 -*-
  2. from pyramid.config import Configurator
  3. import sqlahelper
  4. from sqlalchemy import engine_from_config
  5. from bankaccount.resources import Root
  6. from pyramid.session import UnencryptedCookieSessionFactoryConfig
  7. my_session_factory = UnencryptedCookieSessionFactoryConfig('itsaseekreet')
  8. def main(global_config, **settings):
  9.     """ This function returns a Pyramid WSGI application.
  10.     """
  11.     
  12.     # sqlalchemyを有効に
  13.     engine = engine_from_config(settings)
  14.     sqlahelper.add_engine(engine)
  15.     
  16.     config = Configurator(root_factory=Root,
  17.                             settings=settings,
  18.                             session_factory=my_session_factory)
  19.     
  20.     config.include('pyramid_chameleon')
  21.     # pyramid_tmの読み込みを追加
  22.     config.include('pyramid_tm')
  23.     
  24.     config.add_route('home', '/')
  25.     config.add_route('deposit', '/deposit')
  26.     config.add_route('withdraw', '/withdraw')
  27.     
  28.     config.add_static_view('static', 'bankaccount:static', cache_max_age=3600)
  29.     config.scan()
  30.     
  31.     return config.make_wsgi_app()







データベースの初期化



データベースに接続し、modelに定義したテーブルを作成。
デフォルトレコードを作成します。

この作業はPythonのコンソールで実行しました。


# python
>>> from bankaccount import models
>>> from sqlalchemy import create_engine
>>> models.DBSession.remove()
>>> models.sqlahelper.add_engine(create_engine('postgresql+psycopg2://pgadmin:password@localhost:5432/sample'))
>>> models.Base.metadata.create_all()
>>> b = models.BankAccount(name=u'default')
>>> models.DBSession.add(b)
>>> import transaction
>>> transaction.commit()




実行が終わると、sampleデータベースにbankaccountsが作成され、
nameが「default」となっているレコードが作成されるはずです。


sample=# select * from bankaccounts;
id | name | balance
----+---------+---------
1 | default |     0
(1 row)






実行




# pserve development.ini



を実行して、サーバーを起動します。

ブラウザでhttp://[サーバーIP]:6543/を表示するとこんな画面が表示されました。

416_01.png


Despsitに100と入力して送信すると、100ポイント追加されます。

416_02.png

416_03.png


Withdraowに60を入力して送信すると、残額が40に。

416_04.png

416_05.png


更に60引こうとすると、エラーになりました。

416_06.png


うまく動いてくれているようです。





落穂ひろい



pcreateで出力したファイルを編集したあと実行すると、
こんなエラーになることがあります。


SyntaxError: Non-ASCII character '\xe4' in file /root/bankaccount/bankaccount/__init__.py on line 3,
but no encoding declared; see http://www.python.org/peps/pep-0263.html for details




ファイルの先頭に


  1. # -*- coding:utf-8 -*-



と記載して、ファイルの文字コードを指定してやると、
動作するようになります。

普段無意識に書いているので、しばらく気が付きませんでした。


関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2014/05/20(火) 22:52:01|
  2. Python
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<Ubuntu 14.04でmeditが動作しない場合の対処方法 | ホーム | PythonフレームワークPyramid 1.5のチュートリアル(pcreate)>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/1413-affe4192
この記事にトラックバックする(FC2ブログユーザー)