Edited at

動的に生成されるテーブル定義をSQLAlchemyを使って読み込む方法

More than 5 years have passed since last update.

動的に生成されるテーブル定義を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?