Symfoware

Symfowareについての考察blog

Python ORM Ponyを使ってデータベース操作

なんとなくPython製のORMを調べていたら「Pony」を見つけました。
https://ponyorm.com/

インストールして使用してみます。


インストール



こちらを参考に進めていきます。
https://docs.ponyorm.com/firststeps.html


インストールはeasy_installで行いました。


$ sudo easy_install pony



バージョン0.6.2がインストール出来ました。




テーブルの作成とデータ登録



サンプル通り、プログラムを書いて実行してみます。


  1. from pony.orm import *
  2. db = Database()
  3. class Person(db.Entity):
  4.     name = Required(str)
  5.     age = Required(int)
  6.     cars = Set("Car")
  7. class Car(db.Entity):
  8.     make = Required(str)
  9.     model = Required(str)
  10.     owner = Required(Person)
  11. # コメントを外して有効にすると、コンソールにSQLが表示される
  12. # sql_debug(True)
  13. db.bind('sqlite', 'test_db.sqlite', create_db=True)
  14. db.generate_mapping(create_tables=True)




出来上がったデータベースファイルをSQLiteStudioで表示してみると、
こんな感じのテーブルが出来上がっています。

660_01.png


id列が自動的に生成されていますね。

Person.carsという列は生成されていません。
Setは、子テーブルの指定。

Carテーブルのowner列で、Personオブジェクトを指定し、
Car.owner = Person.idであることを示しているようです。


続いて、データの登録も行ってみます。

John : 20歳
Mary : 22歳 Toyota-Priusを持っている
Bob : 30歳 Ford-Explorerを持っている


  1. from pony.orm import *
  2. db = Database()
  3. class Person(db.Entity):
  4.     name = Required(str)
  5.     age = Required(int)
  6.     cars = Set("Car")
  7. class Car(db.Entity):
  8.     make = Required(str)
  9.     model = Required(str)
  10.     owner = Required(Person)
  11. # コメントを外して有効にすると、コンソールにSQLが表示される
  12. # sql_debug(True)
  13. db.bind('sqlite', 'test_db.sqlite', create_db=True)
  14. db.generate_mapping(create_tables=True)
  15. # トランザクション開始
  16. with db_session:
  17.     p_john = Person(name='John', age=20)
  18.     p_mary = Person(name='Mary', age=22)
  19.     p_bob = Person(name='Bob', age=30)
  20.     c_toyota = Car(make='Toyota', model='Prius', owner=p_mary)
  21.     c_ford = Car(make='Ford', model='Explorer', owner=p_bob)
  22.     commit()




実行後のPersonテーブル

660_02.png

Carテーブル

660_03.png


狙い通りのデータが登録されています。
ちなみに、with db_sessionとしていないと、こんなエラーが発生します。


pony.orm.core.TransactionError: db_session is required when working with the database







データの検索



登録したデータを検索してみます。
まず、20歳より年上の人。(where)


  1. from pony.orm import *
  2. db = Database()
  3. class Person(db.Entity):
  4.     name = Required(str)
  5.     age = Required(int)
  6.     cars = Set("Car")
  7. class Car(db.Entity):
  8.     make = Required(str)
  9.     model = Required(str)
  10.     owner = Required(Person)
  11. # コメントを外して有効にすると、コンソールにSQLが表示される
  12. # sql_debug(True)
  13. db.bind('sqlite', 'test_db.sqlite', create_db=True)
  14. db.generate_mapping(create_tables=True)
  15. with db_session:
  16.     for p in select(p for p in Person if p.age > 20):
  17.         print p.name, p.age




$ python sample.py
Mary 22
Bob 30




全員を名前順で表示。(order by)


  1.     for p in select(p for p in Person).order_by(Person.name):
  2.         print p.name, p.age




$ python sample.py
Bob 30
John 20
Mary 22




名前順で上位2名。(limit)


  1.     for p in select(p for p in Person).order_by(Person.name)[:2]:
  2.         print p.name, p.age




$ python sample.py
Bob 30
John 20




持っている車の台数。(join)


  1.     for p, cnt in select((p, count(p.cars)) for p in Person):
  2.         print p.name, cnt




$ python sample.py
John 0
Mary 1
Bob 1




年齢の最大値。(max)


  1.     print max(p.age for p in Person)




$ python sample.py
30







個別のデータ取得



プライマリキー(この場合id)でデータを取得してみます。


  1. from pony.orm import *
  2. db = Database()
  3. class Person(db.Entity):
  4.     name = Required(str)
  5.     age = Required(int)
  6.     cars = Set("Car")
  7. class Car(db.Entity):
  8.     make = Required(str)
  9.     model = Required(str)
  10.     owner = Required(Person)
  11. # コメントを外して有効にすると、コンソールにSQLが表示される
  12. # sql_debug(True)
  13. db.bind('sqlite', 'test_db.sqlite', create_db=True)
  14. db.generate_mapping(create_tables=True)
  15. with db_session:
  16.     p3 = Person[3]
  17.     print p3.name, p3.age




$ python sample.py
Bob 30




名前を指定して検索。


  1.     p = Person.get(name='Mary')
  2.     print p.name, p.age




$ python sample.py
Mary 22




デバッグ用にshowが便利。


  1.     p = Person.get(name='Mary')
  2.     show(p)




$ python sample.py
instance of Person
id|name|age
--+----+---
2 |Mary|22






データの更新と削除



Maryの年齢を1つ加えて更新してみます。


  1. from pony.orm import *
  2. db = Database()
  3. class Person(db.Entity):
  4.     name = Required(str)
  5.     age = Required(int)
  6.     cars = Set("Car")
  7. class Car(db.Entity):
  8.     make = Required(str)
  9.     model = Required(str)
  10.     owner = Required(Person)
  11. # コメントを外して有効にすると、コンソールにSQLが表示される
  12. # sql_debug(True)
  13. db.bind('sqlite', 'test_db.sqlite', create_db=True)
  14. db.generate_mapping(create_tables=True)
  15. with db_session:
  16.     p = Person.get(name='Mary')
  17.     p.age += 1
  18.     
  19.     commit()




特にsaveとかを実行する必要もなく、commitで更新されました。


  1.     p = Person.get(name='Mary')
  2.     show(p)




$ python sample.py
instance of Person
id|name|age
--+----+---
2 |Mary|23






データを削除する場合はdeleteメソッドを実行します。


  1. from pony.orm import *
  2. db = Database()
  3. class Person(db.Entity):
  4.     name = Required(str)
  5.     age = Required(int)
  6.     cars = Set("Car")
  7. class Car(db.Entity):
  8.     make = Required(str)
  9.     model = Required(str)
  10.     owner = Required(Person)
  11. # コメントを外して有効にすると、コンソールにSQLが表示される
  12. # sql_debug(True)
  13. db.bind('sqlite', 'test_db.sqlite', create_db=True)
  14. db.generate_mapping(create_tables=True)
  15. with db_session:
  16.     p = Person.get(name='Mary')
  17.     p.delete()
  18.     commit()





Personテーブルから削除されました。

660_04.png

合わせて、関連するCarテーブルからもデータが削除されています。

660_05.png



SQL文の直接実行



ORMで表現が難しいデータは、SQLを直接実行したくなります。

Personオブジェクトに対してselectを実行するパターン。


  1. from pony.orm import *
  2. db = Database()
  3. class Person(db.Entity):
  4.     name = Required(str)
  5.     age = Required(int)
  6.     cars = Set("Car")
  7. class Car(db.Entity):
  8.     make = Required(str)
  9.     model = Required(str)
  10.     owner = Required(Person)
  11. # コメントを外して有効にすると、コンソールにSQLが表示される
  12. # sql_debug(True)
  13. db.bind('sqlite', 'test_db.sqlite', create_db=True)
  14. db.generate_mapping(create_tables=True)
  15. with db_session:
  16.     x = 25
  17.     for p in Person.select_by_sql('SELECT * FROM Person p WHERE p.age < $x'):
  18.         print p.name, p.age




$ python sample.py
John 20




Detabaseオブジェクトに対してSQLを実行するパターン。


  1. from pony.orm import *
  2. db = Database()
  3. class Person(db.Entity):
  4.     name = Required(str)
  5.     age = Required(int)
  6.     cars = Set("Car")
  7. class Car(db.Entity):
  8.     make = Required(str)
  9.     model = Required(str)
  10.     owner = Required(Person)
  11. # コメントを外して有効にすると、コンソールにSQLが表示される
  12. # sql_debug(True)
  13. db.bind('sqlite', 'test_db.sqlite', create_db=True)
  14. db.generate_mapping(create_tables=True)
  15. with db_session:
  16.     x = 25
  17.     for name in db.select('name FROM Person WHERE age > $x'):
  18.         print name




$ python sample.py
Bob






関連記事

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

  1. 2016/02/03(水) 22:02:21|
  2. Python
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<Ubuntu KVMにWindos 10をインストールする | ホーム | Python TinyDB Custom Storageの作り方>>

コメント

コメントの投稿


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

トラックバック

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