LoginSignup
15
14

More than 5 years have passed since last update.

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

Last updated at Posted at 2014-06-30

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

15
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
14