Flask SQLAlchemy에서 모델 스키마를 동적으로 변경하는 방법
11502 단어 PostgreSQL파이썬FlaskFlask-SQLAlchemy
처음에
최근 종사하고 있는 WEB 시스템입니다만, 로그인 유저마다 DB 스키마가 다른 사양으로,
"사용자 로그인 시 동적으로 스키마를 변경하여 DB 액세스"해야 했습니다.
Flask-SQLAlchemy를 이용해 위의 사양을 실현하려고 했을 때, 동적으로 모델의 스키마를 변경하는 좋은 방법이 좀처럼 발견되지 않고, 1주일 정도 괴로워하면서 고민하고 있었습니다.
하지만! 최근에 드디어 해결할 수 있었으므로, 그다지 스마트하지는 않지만 해결 방법을 써 갑니다.
똑같이 고민하고 있는 사람의 도움이 되면 다행입니다.
검증 환경
전제 지식
검증할 모델
hoge라는 동일한 구조의 테이블이 foo 스키마와 bar 스키마에 있다고 가정합니다.
(아래 코드는 public 스키마에 Hoge 테이블을 만드는 코드)
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] \
= 'postgresql+psycopg2://postgres:postgres@localhost:5432/postgres' # ロカールのデータベース(postgres)に接続
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
class Hoge(db.Model): # public.hogeのモデル
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), unique=True, nullable=False)
db.create_all() # hogeテーブルをデータベースに作成
【해결】type으로 동적으로 모델 클래스 작성
get_model_dict 라는 스키마 지정해 모델의 내용을 돌려주는 함수를 정의해, 스키마의 사전으로부터 type 를 사용해 동적으로 모델 클래스를 생성. 결국 스키마를 키로 한 모델 클래스의 사전을 만들었습니다.
이용시에 스키마를 키로서 모델 클래스 취득하면, 나머지는 보통의 모델 클래스와 동등하게 이용 가능합니다.
유감스러운 점으로서는, 통상의 모델 클래스와 비교해 쓰는 방법이 귀찮은 곳.
일반 모델 클래스처럼 쓰고 싶었지만 좋지 않았습니다. . .
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] \
= 'postgresql+psycopg2://postgres:postgres@localhost:5432/postgres' # ロカールのデータベース(postgres)に接続
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
# モデルクラスの中身を辞書で返す関数
def get_model_dict(schema):
return {
"__tablename__": 'hoge',
"__table_args__": {"schema": schema},
"id": db.Column(db.Integer, primary_key=True),
"name": db.Column(db.String(80), unique=True, nullable=False),
"__repr__": lambda self: "<Hoge id={}, name={}>".format(self.id, self.name) # __repr__メソッドをlambdaで作成
}
# スキーマの辞書
schema_dict = {1: "foo", 2: "bar"}
# スキーマをキーとしたモデルクラスの辞書を作成
# ※typeで作成するクラス名は被らないように!(被ると怒られた)
HogeDict = {v: type("Hoge{}".format(k), (db.Model, ), get_model_dict(v)) for k, v in schema_dict.items()}
# DBにスキーマ作成
db.session.execute("CREATE SCHEMA foo;")
db.session.execute("CREATE SCHEMA bar;")
db.session.commit()
# DBにhogeテーブル作成
db.create_all()
# ***** 以下動作検証 **********
# hogeテーブルにデータ挿入
db.session.add(HogeDict["foo"](name="I am foo"))
db.session.add(HogeDict["bar"](name="I am bar"))
db.session.commit()
# fooスキーマを検索
HogeDict["foo"].query.all()
# [<Hoge id=1, name=I am foo>]
# barスキーマを検索
HogeDict["bar"].query.all()
# [<Hoge id=1, name=I am bar>]
# 後片付け
db.session.execute("DROP SCHEMA foo, bar CASCADE;")
db.session.commit()
이상입니다
Reference
이 문제에 관하여(Flask SQLAlchemy에서 모델 스키마를 동적으로 변경하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/mohenjyotaro/items/3fbfc6e61e4cbf6a389d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)