sqlalchemy 1.4.x(および将来の読者もおそらく2.0.x)の場合モデルが多くのファイルに分散している場合に便利になるようにErotemic回答をうまく拡張できます(このような場合は、適切に実行するときにORMクラスを検索する主な理由ですOOP)。
そのようなクラスを取りBase
、それから作ります:
from sqlalchemy.orm import declarative_base
class BaseModel:
@classmethod
def model_lookup_by_table_name(cls, table_name):
registry_instance = getattr(cls, "registry")
for mapper_ in registry_instance.mappers:
model = mapper_.class_
model_class_name = model.__tablename__
if model_class_name == table_name:
return model
Base = declarative_base(cls=BaseModel)
次に、モデルを個別のモジュールで宣言することにより、 :cls.model_lookup_by_table_name(...)
から派生している限り、何もインポートせずにメソッドを使用できるようになります。Base
user_models.py
from sqlalchemy import Column, Integer
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True)
# ... and other columns
def some_method(self):
# successfully use lookup like this
balance_model = self.model_lookup_by_table_name("balance")
# ...
return balance_model
balance_models.py
from sqlalchemy import Column, Integer
class Balance(Base):
__tablename__ = "balance"
id = Column(Integer, primary_key=True)
# ... other columns
def some_method(self):
# lookup works on every model
user_model = self.model_lookup_by_table_name("user")
# ...
return user_model
そしてそれは期待通りに動作します:
>>> User().some_method()
<class 'balance_models.Balance'>
>>> Balance().some_method()
<class 'user_models.User'>
>>> Base.model_lookup_by_table_name("user")
<class 'user_models.User'>
>>> Base.model_lookup_by_table_name("balance")
<class 'balance_models.Balance'>
functools.lru_cache
パフォーマンスを向上させるために、このメソッドの出力を安全にキャッシュできます(for
不要な場合はPythonループを回避します)。また、同じ方法でルックアップを追加することもできます。たとえば、クラス名(この例のようなテーブル名だけでなく)を使用します。