SlideShare a Scribd company logo
SQLAlchemy
 BPStyle #4
小田切 aodag 篤
 

アクティブレコードとデータマッパー
SQLAlchemy
データマッピング
宣言的な方法
関連
継承
Session
アクティブレコードとデータマッパー

アクティブレコード
クラスとテーブルを1対1に割り当てるマッピング
(オブジェクトと行が対応する)
簡単
融通は利かない
多対多関連ではマッピングされないテーブルが存在する

データマッパー
クラスに対するテーブルマッピングを指定する
柔軟性が高い
ちょっと面倒
多対多関連で関連属性もマッピング可能
SQLAlchemy




 データマッパータイプのORマッパー
 SQLをPythonオブジェクトで構築
 Unit of workパターン
対応データベース

  SQLite
  MySQL
  PostgreSQL
  Firebird
  Oracle
  SQL Server
  DB2
など
データマッピング(1) スキーマ定義

person_table = Table("person", meta,
  Column("person_id", Integer, primary_key),
  Column("first_name", Unicode(20)),
  Column("last_name", Unicode(20)),
  Column("birthday", Date))


要するにテーブル
データマッピング(2) マッピング先

class Person(object):
   """ A person
   """

   def __init__(self, first_name, last_name, birthday):
      self.first_name, self.last_name, self.birthday = first_name,
last_name, birthday


普通のクラス
データマッピング(3) マッピング

person_mapper = mapper(Person, person_table)

Columnがそのままアトリビュートになる
 




    ぶっちゃけめんどくさい
宣言的マッピング

Base = declarative_base()

class Person(Base):
   __tablename__ = 'person'
   person_id = Column(Integer, primary_key=True)
   first_name = Column(Unicode(20)),
   last_name = Column(Unicode(20)),
   birthday = Column(Date))

クラスとスキーマを同時に定義
関連マッピング

class Employee(Base):
   __tablename__ = 'employee'
   id = Column(Integer, primary_key=True)
   .....
   company_id = Column(Integer,
                    ForeignKey('company.id'))

class Company(Base):
   __tablename__ = 'company'
   id = Column(Integer, primary_key=True)
   employees = relation(Employee, backref="company")
多対多

user_keyword_table = Table('user_keyword', meta,
  Column('user_id', ForeignKey('user.id')),
  Column('keyword_id', ForeignKey('keyword.id')))

class User(Base):
   id = Column(Integer, primary_key=True)

class Keyword(Base):
   id = Column(Integer, primary_key=True)
   users = relation(User, backref='keywords',
               secondary=user_keyword_table)
関連属性(1)

class User(Base):
   id = Column(Integer, primary_key=True)
   name = Column(String(255), unique=True)

class Keyword(Base):
   id = Column(Integer, primary_key=True)
   word = Column(String(255), unique=True)
関連属性(2)

class UserKeywords(Base):
   user_id = Column(Integer, ForeignKey('user.id'))
   keyword_id = Column(Integer, ForeignKey('keyword.id'))
   registered = Column(DateTime)
   kw= relation(Keyword, backref="users")
   us = relation(User, backref="keywords")
 

user = User()
user.name = 'aodag'
keyword = Keyword()
keyword.word = 'python'

user_keyword = UserKeyword()
user_keyword.registered = datetime.now()
user_keyword.us = user
user_keyword.kw= keyword
 

user.kw[0].registered
user.kw[0].kw.word
word.us[0].user.name

2HOPするのがうざい
関連属性 AssociationProxy

class User(Base):
   id = Column(Integer, primary_key=True)
   name = Column(String(255), unique=True)
   keywords = association_proxy('kw', 'keyword')

class Keyword(Base):
   id = Column(Integer, primary_key=True)
   word = Column(String(255), unique=True)
   users= association_proxy('us', 'user')
 

user.kw[0].registered
user.keywords[0].word
keyword.users[0].name
 

user.kw[0].keyword.word
-> user.keyword[0].word

keyword.us[0].user.name
-> keyword.users[0].name
継承

RDBの継承実装方法

結合テーブル
スーパータイプのテーブルとサブタイプ固有のデータを持つテーブ
ル

単一テーブル
すべてのサブタイプのデータを含む1テーブル

完全テーブル
サブタイプごとにすべてのデータを持つテーブル
継承(1) スーパークラスの設定

class Person(Base):
   ...
   typename = Column(String(20))
   __mapper_args__ = {'polymorphic_on':'typename'}

タイプフラグのカラムを追加
オプションで、カラムを指定
継承(2) 結合テーブルの場合

class Employee(Person):
   __tablename__ = 'employee'
   employee_id = Column(Integer,
                      ForeignKey('person.person_id'))
   __mapper_args__ = {'polymorphic_identity':'employee'}

サブタイプはテーブルを持つ
スーパータイプのテーブルを参照する外部参照制約
タイプフラグの値を指定
継承(2) 単一テーブル継承

class Employee(Person):
   __mapper_args__ = {'polymorphic_identity':'employee'}

サブタイプはテーブルを持たない
継承(3) 完全テーブル

class Employee(Person):
   __tablename__ = 'employee'
   person_id = Column(Integer, primary_key=True)
   first_name = Column(Unicode(20)),
   last_name = Column(Unicode(20)),
   birthday = Column(Date))
   __mapper_args__ = {'concrete':True}

サブタイプはテーブルを持つ
オプションで完全に別テーブルとする指定
スーパータイプにはタイプフラグが必要ない
カラムを再度定義
Unit of work

データ処理をマーキングして管理
一度にデータベースに反映

メモリ上でのトランザクション処理
SessionとDB接続

DB接続情報
engine = create_engine('sqlite:///')

クラスファクトリ
Session = sessionmaker(bind=engine)

セッションオブジェクト
session = Session()
Session

p = Person(u'篤', u'小田切', datetime(1979, 8, 2))
session.add(p)
p = Person(u'John', u'Doe', datetime(1970, 1, 1))
session.add(p)

session.commit()


新規オブジェクトは、セッションに追加する
Session

p = session.query(Person).filter_by(id=1)
p.birthday = date.today()

session.commit()

p = session.query(Person).filter_by(id=1)
p.delete()
session.commit()

sessionから取り出したオブジェクトはそのまま。
scoped_session

スレッドローカルなモノステートオブジェクト

Session = scoped_session(sessionmaker(bind=engine))
Session.query(...)

直接グローバルオブジェクトでメソッド呼び出しできる。
同一スレッド内であれば、同一セッション。

内部状態のリセットはremoveメソッドで。
Session.remove()
マルチDB

MasterSession = session_maker(bind=create_engine('mysql:
//db1/db')

SlaveSession =
session_maker(bind=create_engine('sqlite://db2/db')

p = Person(...)
s1 = MasterSession()
s1.add()
s1.commit()

s2 = SlaveSession()
s2.query(Person).filter_by(id=1)
まとめ

恐ろしく柔軟
今回紹介したのはSqlAlchemyができることの1/10くらい
その他、
コネクションプロキシ
2フェーズコミット
複数テーブルから1クラスにマッピング
1テーブルから複数クラスにマッピング
クエリからクラスにマッピング
関連の実装クラスをdictやsetに変更
アトリビュート単位での遅延ローディング
垂直分割、水平分割(sharding)の対応
などなど
 


足りないのはadminだけ!
多分FormAlchemyで作れば、それほど問題ないかと。
マイグレーションは、sqlalchemy-migrate

More Related Content

PDF
Sqlalchemy sqlの錬金術
PDF
Slides python elixir
PDF
ScalikeJDBC Tutorial for Beginners
PPTX
Django - sql alchemy - jquery
PPTX
A to Z about JQuery - Become Newbie to Expert Java Developer
ODP
Slickdemo
PPTX
Increase your quality and performance
PPTX
NoSQL Endgame Percona Live Online 2020
Sqlalchemy sqlの錬金術
Slides python elixir
ScalikeJDBC Tutorial for Beginners
Django - sql alchemy - jquery
A to Z about JQuery - Become Newbie to Expert Java Developer
Slickdemo
Increase your quality and performance
NoSQL Endgame Percona Live Online 2020

What's hot (20)

PDF
Java for beginners
PDF
The Ring programming language version 1.10 book - Part 47 of 212
PDF
Introduction to Active Record - Silicon Valley Ruby Conference 2007
PPTX
GreenDao Introduction
PPTX
Windows 8 JavaScript (Wonderland)
PPT
Apache Utilities At Work V5
PDF
C# Advanced L03-XML+LINQ to XML
PDF
Kabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_tech
PPTX
Web Security - Hands-on
PPTX
Omnisearch in AEM 6.2 - Search All the Things
PPT
Spsl v unit - final
PDF
Cassandra intro
PDF
Database madness with_mongoengine_and_sql_alchemy
PPTX
J Query The Write Less Do More Javascript Library
PDF
Building DSLs With Eclipse
PDF
Green dao
PDF
Swift for TensorFlow - CoreML Personalization
PDF
Be Smart, Constrain Your Types to Free Your Brain!
PDF
Green dao
PDF
CSharp Advanced L05-Attributes+Reflection
Java for beginners
The Ring programming language version 1.10 book - Part 47 of 212
Introduction to Active Record - Silicon Valley Ruby Conference 2007
GreenDao Introduction
Windows 8 JavaScript (Wonderland)
Apache Utilities At Work V5
C# Advanced L03-XML+LINQ to XML
Kabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_tech
Web Security - Hands-on
Omnisearch in AEM 6.2 - Search All the Things
Spsl v unit - final
Cassandra intro
Database madness with_mongoengine_and_sql_alchemy
J Query The Write Less Do More Javascript Library
Building DSLs With Eclipse
Green dao
Swift for TensorFlow - CoreML Personalization
Be Smart, Constrain Your Types to Free Your Brain!
Green dao
CSharp Advanced L05-Attributes+Reflection
Ad

Viewers also liked (8)

PDF
フレームワークなしでWSGIプログラミング
PDF
Setup.pysetup.cfg
PDF
How To Drink Wsgi
PDF
メタクラスプロトコル
PPTX
Clack meetup #1 lt
PDF
PDF
Pythonすいーつ部
PDF
Python3 移行への軌跡
フレームワークなしでWSGIプログラミング
Setup.pysetup.cfg
How To Drink Wsgi
メタクラスプロトコル
Clack meetup #1 lt
Pythonすいーつ部
Python3 移行への軌跡
Ad

Similar to Sql alchemy bpstyle_4 (6)

PDF
Scala ActiveRecord
PDF
Cassandraに不向きなcassandraデータモデリング基礎
 
PDF
Cassandraに不向きなcassandraデータモデリング基礎 / Data Modeling concepts for NoSQL weak point
PDF
20210928_pgunconf_hll_count
PDF
DataMapper
PDF
DataMapper @ RubyEnRails2009
Scala ActiveRecord
Cassandraに不向きなcassandraデータモデリング基礎
 
Cassandraに不向きなcassandraデータモデリング基礎 / Data Modeling concepts for NoSQL weak point
20210928_pgunconf_hll_count
DataMapper
DataMapper @ RubyEnRails2009

More from Atsushi Odagiri (20)

PDF
みんなのPython勉強会#77 パッケージングしよう
PDF
async/await の向こう側 PyCon Kyushu 2022
PDF
パッケージングの呼び声 Python Charity Talks in Japan 2021.02
PDF
eggとはなんだったのか 栄光のsetuptools
PDF
pyconjp 2019 LT 今日のsetuptools
PDF
Pythonでの開発を効率的に進めるためのツール設定
PDF
Pythonとパッケージングと私
PDF
パッケージングを支える技術 pyconjp2016
PDF
Pyramid入門
PDF
パッケージングの今
PDF
パッケージングの今と未来
PDF
パッケージングの今と未来
PDF
Bplt11 form alchemy
PDF
Python3でwebアプリ
PDF
Pyconjp2012 memory-of-europython
PDF
What makes pyramid unique
PDF
エキPy lt repoze.whoの紹介
PDF
World plonedaylt
PDF
BPStudy#54 そろそろPython3
PDF
Form libraries
みんなのPython勉強会#77 パッケージングしよう
async/await の向こう側 PyCon Kyushu 2022
パッケージングの呼び声 Python Charity Talks in Japan 2021.02
eggとはなんだったのか 栄光のsetuptools
pyconjp 2019 LT 今日のsetuptools
Pythonでの開発を効率的に進めるためのツール設定
Pythonとパッケージングと私
パッケージングを支える技術 pyconjp2016
Pyramid入門
パッケージングの今
パッケージングの今と未来
パッケージングの今と未来
Bplt11 form alchemy
Python3でwebアプリ
Pyconjp2012 memory-of-europython
What makes pyramid unique
エキPy lt repoze.whoの紹介
World plonedaylt
BPStudy#54 そろそろPython3
Form libraries

Sql alchemy bpstyle_4