ORM:SQLAlchemy初認識
8393 ワード
ORM: Object Relational Mapper.
現在、PythonにはデータベースをPythonのObjectsオブジェクトにイメージできるORMツールがたくさんあります.中でも有名なのはDjangoのORM、SQLAlchemy、PostgreSQLなどです.
伝統的な自分でSQL文を編んだり、モデルを作ったり、データベースに接続したりする方法を捨てて、
データクエリでさえSQLAlchemyはSQL文の代わりに、MongoDBのような
インストール:
Driversのインストール:
SQLAlchemy自身はデータベースdriverを持たず、自分でインストールし、接続時に指定する必要があります.これらのdriverは、実際にはデータベースに手動で接続するために使用されたパッケージです.SQLAlchemyは私たちの代わりにこれらの同じパッケージを使用しているだけです.
データベースの接続
sqliteのORMエンジンを作成します.
MySQLのORMエンジンを作成します.
データベースの場所:
Create Tableテーブルの作成
注意:SQL文とは異なり、SQLAlchemyのテーブル名は
大文字と小文字を完全に区別!
Schemaテーブルを作成します(単純なテーブルで、ORMオブジェクトは含まれません):
テーブルを含むORMオブジェクトを作成します.
通常テーブルTableとORMオブジェクトで作成されたテーブルの違いは何ですか?彼らがデータベースで作成したのは、まったく同じテーブルです.唯一の違いは、Tableが作成したORMオブジェクトを含まないこと、つまりPythonオブジェクトを直接操作する機能を提供しないことです.このような利点は,関連作用のみのテーブルが多く,ORMオブジェクトを生成する必要がないことである.
データベース内のテーブルの削除
設計やデバッグの過程で、テーブルを頻繁に変更することが多いので、テーブルを作成する前にテストデータベースのテーブルを消去してから、新しい定義を作成する必要があります.
Insertion挿入データ
データベースにデータを追加するには、次の手順に従います.
注意:ここの
一括追加データ(add_all()への入力リスト):
各データを追加するときに自動flush():
具体的な理由は、次のセクション「データの有効化」を参照してください.
Take effectデータの有効化
SQLAlchemyの
注意:
この2つの順序は、もちろんテーブルを作成してからデータを挿入します.
ただ,この原理を知れば,符号化において自由に運用できる.たとえば、
その後,データ挿入作業を再開し,sessionを利用した.
セッション中は、プライマリ・キーの外部キーIDを相互に参照する場合もあります.ただし、この場合、最終的な
データの更新/削除
更新:
Get Primary Key Valueプライマリ・キー値の取得
この問題は私に多くの時間を費やして照会を探求して、その解を得られなくて、やっともとは明らかなことであることを理解しました.
参考:SQLAlchemyで新しく挿入したデータのidを返しますか?
セッションやengineでデータを挿入する前に、ORMから作成したオブジェクトのプロパティ値を直接参照できます.しかし、このときはどうしても
このときプライマリ・キーはまだデータベースに挿入されていないため、
なぜサブテーブルの を参照する必要がある. ??
では、プライマリ・キーIDはどのように取得すればいいのでしょうか.
Stackoverflow:sqlalchemy flush()and get inserted id?再参照:sqlalchemy挿入されたidを取得再参照:Sqlalchemy;プライマリ・キーを事前に存在するデータベース・テーブルに設定します(sqliteは使用しません).
データを挿入する前に、プライマリ・キーなどの SQLAlchemyを直接利用してクラスの直接的な内部関連を確立し、ID を直接使用しないプライマリテーブルにデータを挿入し、別のセッションが有効になった後、queryで対応するオブジェクトを取得してIDを取得します. (*)プライマリテーブルは、まず を使用する. primaryキーを使用せずに、自分でIDを手動で作成し、勝手に取得します.
推奨方法は次のとおりです.
すなわち、オブジェクトを新しく作成するたびに、すぐにsession.add(..),そしてすぐにflush()は、すべての文末を追加して、セッションします.commit().
Queryクエリー
注意:queryはセッションによって行われます.つまり、
ここで示すqueryクエリは、すべて
参照:pythonsheets-Object Relational basic query
クエリーデータ:
一般的なクエリー方法:
現在、PythonにはデータベースをPythonのObjectsオブジェクトにイメージできるORMツールがたくさんあります.中でも有名なのはDjangoのORM、SQLAlchemy、PostgreSQLなどです.
SQLAlchemy
より多くの人がメンテナンスしており、機能もそろっています.だから一般的には私たちのプリファレンスです.SQLAlchemy
の利用者にとって、最初にデータベースに接続すれば、Sqlite、MySQL、何でも、後の処理方法はまったく同じです.この利便性も人気の理由です.伝統的な自分でSQL文を編んだり、モデルを作ったり、データベースに接続したりする方法を捨てて、
SQLAlchemy
は直接これらのものをブラックボックスに包んで、私たちにまったく管理する必要がありません.SQL-Injection注入というものまで防いでくれました.これにより,データベースへの接続において,少なくとも半分以上のコードを節約できるといえる.データクエリでさえSQLAlchemyはSQL文の代わりに、MongoDBのような
Object.query.filter_by(name='Jason').all()
のような専門的な方法を使用しています.インストール:
# sqlalchemy
$ pip install sqlalchemy
Driversのインストール:
# Sqlite
# ,Python
# MySQL
$ pip install pymysql
# Postgresql
$ pip install psycopg2
SQLAlchemy自身はデータベースdriverを持たず、自分でインストールし、接続時に指定する必要があります.これらのdriverは、実際にはデータベースに手動で接続するために使用されたパッケージです.SQLAlchemyは私たちの代わりにこれらの同じパッケージを使用しているだけです.
データベースの接続
sqliteのORMエンジンを作成します.
from sqlalchemy import create_engine
# :sqlite:///
engine = create_engine('sqlite:///foo.db', echo=True)
MySQLのORMエンジンを作成します.
from sqlalchemy import create_engine
# :dialect+driver://username:password@host:port/database
engine = create_engine('mysql+pymysql://root:password123@localhost/db_test_01', echo=True)
データベースの場所:
# (////), /tmp/mydatabase.db
engine = create_engine('sqlite:////tmp/mydatabase.db')
# 「 」 (/// ///./)
engine = create_engine('sqlite:///mydatabase.db')
# 「 」 (///../)
engine = create_engine('sqlite:///../mydatabase.db')
# 「 」
import os
cwd = os.path.split(os.path.realpath(__file__))[0]
engine = create_engine('sqlite:///{}/mydatabase.db'.format(cwd))
Create Tableテーブルの作成
注意:SQL文とは異なり、SQLAlchemyのテーブル名は
大文字と小文字を完全に区別!
Schemaテーブルを作成します(単純なテーブルで、ORMオブジェクトは含まれません):
from sqlalchemy import create_engine, MetaData
from sqlalchemy import Table, Column
from sqlalchemy import Integer, String, ForeignKey
engine = create_engine('mysql+pymysql://root:password123@localhost/db_test_01', echo=True)
metadata = MetaData(engine)
#
user_table = Table( 'tb_user', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(50)),
Column('fullname', String(100))
)
#
metadata.create_all()
テーブルを含むORMオブジェクトを作成します.
#
from sqlalchemy import create_engine
#
from sqlalchemy import Column, Integer, String, ForeignKey
# ORM
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'tb_Person'
id = Column('id', Integer, primary_key=True)
username = Column('username', String, unique=True)
engine = create_engine('sqlite:///test.sqlite', echo=True)
Base.metadata.create_all(bind=engine)
通常テーブルTableとORMオブジェクトで作成されたテーブルの違いは何ですか?彼らがデータベースで作成したのは、まったく同じテーブルです.唯一の違いは、Tableが作成したORMオブジェクトを含まないこと、つまりPythonオブジェクトを直接操作する機能を提供しないことです.このような利点は,関連作用のみのテーブルが多く,ORMオブジェクトを生成する必要がないことである.
データベース内のテーブルの削除
# engine = ...
# Base = ...
# ORM , User
User.__table__.drop(engine)
#
Base.metadata.drop_all(engine)
設計やデバッグの過程で、テーブルを頻繁に変更することが多いので、テーブルを作成する前にテストデータベースのテーブルを消去してから、新しい定義を作成する必要があります.
Insertion挿入データ
データベースにデータを追加するには、次の手順に従います.
# ...
# session ( )
from sqlalchemy.orm import sessionmaker, relationship
user = User()
user.id = 1
user.username = 'Jason'
Session = sessionmaker(bind=engine)
session = Session()
session.add(user)
session.commit()
session.close()
注意:ここの
session
とウェブサイトのsessionの概念は少し違います.ここではcommitがデータベースの変動をコミットするためのツールです.一括追加データ(add_all()への入力リスト):
session.add_all( [user1, user2, user3] )
各データを追加するときに自動flush():
session = sessionmaker(bind=engine, autoflush=True)
autoflush
は、session.add()
のたびにsession.flush()
が自動的に実行される.すなわち、データベースを挿入する前に、プライマリ・キーIDなどのすべてのオブジェクトの動的データがメモリに生成される.一般的にデフォルトはfalseを選択します.効率に影響を与えるからです.session.flush()
を手動で実行するには、必要な場合が望ましい.具体的な理由は、次のセクション「データの有効化」を参照してください.
Take effectデータの有効化
SQLAlchemyの
create_all()
とsession.commit()
は、pythonファイルで定義されたオブジェクトをデータベースで直接有効にする文です.これまでは、どのように定義しても、データベースではなくメモリにデータが格納されていました.注意:
create_all
は、insertに関係なくテーブル構造の作成を有効にするだけです.session.commit()
は、追加されたデータを有効にするだけで、テーブル構造を担当しません.この2つの順序は、もちろんテーブルを作成してからデータを挿入します.
ただ,この原理を知れば,符号化において自由に運用できる.たとえば、
create_engine()
でエンジンを作成する場合でも、ファイルヘッダ、すなわちすべてのORM定義の前に書く必要はありません.create_engine
は、すべてのORMクラスおよびSchemaテーブルの後に定義すればよい.その後,データ挿入作業を再開し,sessionを利用した.
セッション中は、プライマリ・キーの外部キーIDを相互に参照する場合もあります.ただし、この場合、最終的な
session.commit()
を使用してデータベースにデータを送信していないため、これらのIDには値がありません.解決策は内蔵の方法session.flush()
を利用して、sessionに追加されたすべてのオブジェクトをデータに埋め込むことですが、この時点でデータベースに提出されていません.ただ、私たちの内部では正常に各種IDにアクセスすることができます.データの更新/削除
更新:
# Get a row of data
me = session.query(User).filter_by(username='Jason').first()
# Method 1:
me.age += 1
session.commit()
# Method 2:
session.query().filter(
User.username == 'Jason'
).update(
{"age": (User.age +1)}
)
session.commit()
# Method 3:
setattr(user, 'age', user.age+1)
session.commit()
Get Primary Key Valueプライマリ・キー値の取得
#sqlalchemy can't get primary key
, #sqlalchemy
この問題は私に多くの時間を費やして照会を探求して、その解を得られなくて、やっともとは明らかなことであることを理解しました.
参考:SQLAlchemyで新しく挿入したデータのidを返しますか?
セッションやengineでデータを挿入する前に、ORMから作成したオブジェクトのプロパティ値を直接参照できます.しかし、このときはどうしても
primar_key
のプライマリ・キー列の値が得られない.このときプライマリ・キーはまだデータベースに挿入されていないため、
として、データベースが有効にならない前にNoneとなります.なぜ
value of primary_key
を取得する必要がありますか?次のようなシナリオを考慮します.foreign key
外部キーは、プライマリテーブルのid では、プライマリ・キーIDはどのように取得すればいいのでしょうか.
Stackoverflow:sqlalchemy flush()and get inserted id?再参照:sqlalchemy挿入されたidを取得再参照:Sqlalchemy;プライマリ・キーを事前に存在するデータベース・テーブルに設定します(sqliteは使用しません).
データを挿入する前に、プライマリ・キーなどの
の値を取得するには、次の方法があります.session.add(..)
、さらにsession.flush()
を使用し、その後IDを取得することができ、最後にsession.commit()
推奨方法は次のとおりです.
すなわち、オブジェクトを新しく作成するたびに、すぐにsession.add(..),そしてすぐにflush()は、すべての文末を追加して、セッションします.commit().
Queryクエリー
注意:queryはセッションによって行われます.つまり、
session.commit()
以降にクエリーを行わなければなりません.そうしないと、エラーが発生します.ここで示すqueryクエリは、すべて
.これを理解することは重要です.オブジェクトがデータベースに挿入される前に、多くのプライマリ・キー、外部キーなどのコンテンツが存在せず、クエリーできないためです.参照:pythonsheets-Object Relational basic query
クエリーデータ:
session.commit()
# ...
users = session.query(User).all()
# User :>>> [ , , .... ]
for u in users:
print(u.id, u.username)
一般的なクエリー方法:
# ORM .query(ORM )
>>> session.query( User ).all() # All rows of data
>>> session.query( User ).first() # First row of data as an object
# .order_by( . )
>>> session.query(User).order_by( User.birth ).all()
# .filter( True/False )
>>> session.query(User).filter( User.name != 'Jason' ).all()
>>> session.query(User).filter( User.name.like('%ed%') ).all() # Fuzzy search
>>> session.query(User).filter( User.id in [1, 2, 3] ).all() # IN
>>> session.query(User).filter( ~ User.id in [4, 5, 6] ).all() # NOT IN
>>> session.query(User).filter( User.school == 'MIT', User.age < 24 ).first() # AND
>>> session.query(User).filter( _or(User.school == 'MIT', User.age < 24) ).first() # OR