動的に生成されるテーブル定義をSQLAlchemyを使って読み込む方法
タイトルのことをやりたい!と思って調べたのでメモ。
結論から言うと、組み込み関数のtypeを使ってマッピングのオブジェクトを作ってやればOK。
例えばこんな感じで書く。
engine = create_engine(データベースURL, echo=True, encoding='utf-8')
base = declarative_base(engine)
dic = {
'__tablename__': テーブル名,
'__table_args__': {'autoload': True}}}
obj = type('MyObject', (base,), dic)
ポイントとしては、既存のテーブルからマッピングを作るautoload = True
を設定すること。
サンプル
サンプルコード
sql_sample.py
# -*- coding: utf-8 -*-
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
schema = 'sqlite:///test.db'
engine = create_engine(schema, echo=False, encoding='utf-8')
base = declarative_base(engine)
session = sessionmaker(bind=engine)()
management_dic = {
'__tablename__': 'management',
'__table_args__': {'autoload': True}}
management_object = type('management_object', (base,), management_dic)
fetch_management = session.query(management_object).all()
for management_row_object in fetch_management:
folder_table_dic = {
'__tablename__': management_row_object.folder_table_name,
'__table_args__': {'autoload': True}}
folder_object_name = management_row_object.folder_table_name.encode('utf-8')
folder_object = type(folder_object_name, (base,), folder_table_dic)
fetch_folder = session.query(folder_object).all()
print "-" * 32
print "table_name: %s" % folder_object_name
print "-" * 32
for row in fetch_folder:
print " fid: %s, file_name: %s" % (row.fid, row.file_name)
print
サンプルコードを使うためのデータベース設定
動的に作成するテーブルを管理するテーブル(management)
tid | folder_table_id |
---|---|
0 | folder_0000 |
1 | folder_0001 |
management.sql
CREATE TABLE management(
tid INTEGER NOT NULL PRIMARY KEY,
folder_table_name TEXT NOT NULL);
INSERT INTO management(tid, folder_table_name) VALUES (0,'folder_0000');
INSERT INTO management(tid, folder_table_name) VALUES (1,'folder_0001');
動的に生成されたテーブル(folder_0000)
fid | file_name |
---|---|
0 | ham.txt |
1 | spam.txt |
2 | egg.txt |
folder_0000.sql
CREATE TABLE folder_0000(
fid INTEGER NOT NULL PRIMARY KEY,
file_name TEXT NOT NULL
);
INSERT INTO folder_0000(fid, file_name) VALUES (0,'ham.txt');
INSERT INTO folder_0000(fid, file_name) VALUES (1,'spam.txt');
INSERT INTO folder_0000(fid, file_name) VALUES (2,'egg.txt');
動的に生成されたテーブル(folder_0001)
fid | file_name |
---|---|
0 | foo.txt |
1 | bar.txt |
folder_0001.sql
CREATE TABLE folder_0001(
fid INTEGER NOT NULL PRIMARY KEY,
file_name TEXT NOT NULL
);
INSERT INTO folder_0001(fid, file_name) VALUES (0,'foo.txt');
INSERT INTO folder_0001(fid, file_name) VALUES (1,'bar.txt');
サンプルの実行
sqlite3 test.db < management.sql
sqlite3 test.db < folder_0000.sql
sqlite3 test.db < folder_0001.sql
python sql_sample.py
サンプルの実行結果
--------------------------------
table_name: folder_0000
--------------------------------
fid: 0, file_name: ham.txt
fid: 1, file_name: spam.txt
fid: 2, file_name: egg.txt
--------------------------------
table_name: folder_0001
--------------------------------
fid: 0, file_name: foo.txt
fid: 1, file_name: bar.txt
参考
Python > Documentation > Python標準ライブラリ > 2.組み込み関数
Dynamically setting _tablename_ for sharding in SQLAlchemy?