概要
SQLArchemy は Python で使える ORM です
簡単な CRUD 操作からマイグレーションまで幅広い機能を提供しています
今回は簡単なテーブルの作成から CRUD 操作まで行ってみました
環境
- macOS X 10.13.6
- Python 3.6.5
- SQLAlchemy 1.2.10
- MySQL Server 5.7.22
インストール
- pipenv install SQLAlchemy mysqlclient
今回は MySQL にアクセスするので mysqlclient も合わせてインストールします
Tips
おそらく ModuleNotFoundError: No module named 'MySQLdb'
のエラーが出ると思います
そして pipenv install MySQL-Python
をインストールしようとしたのですがどうやらまだ Python3 に対応していないようです
なので PyMySQL をインストールしようとしたのですが状況は変わらずで最終的に mysqlclient
をインストールすることで解決しました
事前準備
mysql -u root -p -e "create database test;"
test データベースを作成しておきましょう
とりあえず接続してみる
from sqlalchemy import create_engine
url = 'mysql+mysqldb://user:password@localhost/test?charset=utf8'
engine = create_engine(url, echo=True)
- pipenv run python3 test1.py
こんな感じです
ユーザ、パスワードの部分は適当に変更してください
test
データベースに接続しています
Base クラスを作成して users テーブルの作成準備をする
test1.py にいろいろ追記していきます
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
url = 'mysql+mysqldb://root@localhost/test?charset=utf8'
engine = create_engine(url, echo=True)
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String(50))
fullname = Column(String(100))
password = Column(String(100))
def __repr__(self):
return "<User(name='%s', fullname='%s', password='%s')>" % (self.name, self.fullname, self.password)
- pipenv run python3 test2.py
まず User クラスは Base クラスを継承します
そして __tablename__
変数でテーブル名を指定します
あとは Column
を使ってテーブルに定義するカラムを定義します
__repr__
は必須ではないですが実装しておくとレスポンスをキレイに見せることができます
テーブルを作成する
先ほどのスキーマ定義から実際にテーブルを作成するところまで追加します
と言っても最後の 1 行を追加しているだけです (Base.metadata.create_all(engine)
)
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
url = 'mysql+mysqldb://root@localhost/test?charset=utf8'
engine = create_engine(url, echo=True)
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String(50))
fullname = Column(String(100))
password = Column(String(100))
def __repr__(self):
return "<User(name='%s', fullname='%s', password='%s')>" % (self.name, self.fullname, self.password)
Base.metadata.create_all(engine)
- pipenv run python3 test3.py
これで test データベースは以下に users というテーブルが作成されています
mysql -u user -p password test -e "desc users;"
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(50) | YES | | NULL | |
| fullname | varchar(100) | YES | | NULL | |
| password | varchar(100) | YES | | NULL | |
+----------+--------------+------+-----+---------+----------------+
sqlalchemy.exc.CompileError: (in table 'users', column 'name'): VARCHAR requires a length on dialect mysql
というエラーになる場合はカラムを定義している String
の部分で引数に文字数を指定しているか確認してください
VARCHAR はちゃんと文字数制限を入れないとエラーとなります
データを登録する
engine を元に Session を作成することでテーブルにアクセスすることができます
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
url = 'mysql+mysqldb://root@localhost/test?charset=utf8'
engine = create_engine(url, echo=True)
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String(50))
fullname = Column(String(100))
password = Column(String(100))
def __repr__(self):
return "<User(name='%s', fullname='%s', password='%s')>" % (self.name, self.fullname, self.password)
Base.metadata.create_all(engine)
u1= User(name='hawk', fullname='hawksnowlog', password='xxxxxxx')
Session = sessionmaker(bind=engine)
session = Session()
session.add(u1)
session.commit()
最後の session.commit()
するまでデータは挿入されません
なのでユーザを複数人登録したり更新処理なども行ってから commit
することができます
いわゆるトランザクション処理になります
ちなみに commit
する前の状態にロールバックしたい場合は session.rollback()
を呼び出せば OK です
データを取得する
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
url = 'mysql+mysqldb://root@localhost/test?charset=utf8'
engine = create_engine(url, echo=True)
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String(50))
fullname = Column(String(100))
password = Column(String(100))
def __repr__(self):
return "<User(name='%s', fullname='%s', password='%s')>" % (self.name, self.fullname, self.password)
Base.metadata.create_all(engine)
u1= User(name='hawk', fullname='hawksnowlog', password='xxxxxxx')
Session = sessionmaker(bind=engine)
session = Session()
for i in session.query(User).order_by(User.id):
print(i.name)
登録する部分を削って取得する部分を足します
いわゆる SELECT 文は session.query()
を使います
とりあえず order_by
を使っていますがデータは少ないので何でも OK です
SELECT した結果 User クラスの配列を返したい場合は session.query(User).order_by(User.id).all()
を呼び出せば OK です
データを削除する
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
url = 'mysql+mysqldb://root@localhost/test?charset=utf8'
engine = create_engine(url, echo=True)
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String(50))
fullname = Column(String(100))
password = Column(String(100))
def __repr__(self):
return "<User(name='%s', fullname='%s', password='%s')>" % (self.name, self.fullname, self.password)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
u1 = session.query(User).get(1)
session.delete(u1)
session.commit()
一旦 SELECT してからそのオブジェクトを削除します
あとは commit すれば OK です
データを更新する
削除とほぼ同じです
SELECT してそのオブジェクトの attribute に対してアクセスするだけです
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
url = 'mysql+mysqldb://root@localhost/test?charset=utf8'
engine = create_engine(url, echo=True)
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String(50))
fullname = Column(String(100))
password = Column(String(100))
def __repr__(self):
return "<User(name='%s', fullname='%s', password='%s')>" % (self.name, self.fullname, self.password)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
u1 = session.query(User).get(2)
u1.password = 'XXXXXXXX'
session.commit()
最後に commit するのを忘れずに
最後に
Python3 で SQLAlchemy に入門してみました
慣れれば簡単に使えると思います
今回紹介した内容はかなり基本的なことだけです
もっと複雑なクエリの発行や外部キーの制約なども行えます
いろいろなサイトに書いてありましたが一番役に立つのは参考サイトにある公式サイトのチュートリアルなので、これをベースに勉強すると良いと思います
この記事もそのチュートリアルを元に作成しています
参考サイト