これは、2 つのデータベース (このモデルが使用するのは mssql) に対して tg2 を使用するプロジェクトの一部です。読み取り/書き込みが必要なテーブルは別のアプリケーションで作成および管理されるため、ターボギアにテーブルを上書き/変更させたくありません-既存のテーブルで作業するだけです-したがって、sqlalchemyの魔法の「自動ロード」リフレクションを使用します(私もmssql db のこのテーブル構成のすべての詳細を知っているわけではありません)リフレクションの一部はクラス内で行われmodel.__init__.py
、クラス内では行われません(一部の sqlalchemy チュートリアルが示唆するように) tg2 内部作業のため
これは私が得るエラーメッセージです:(dbのテーブル名はSOMETABLEで、私のアプリではクラスはアクティビティです)
sqlalchemy.exc.ArgumentError: Mapper Mapper|Activities|SOMETABLE could not
assemble any primary key columns for mapped table 'SOMETABLE'
これは活動クラスです:
class Activities(DeclarativeBase2):
__tablename__ = 'SOMETABLE'
#tried the classic way, I used in another place without tg but didn't work here - the reflection should be outside the class
#__table_args__= {'autoload':True
#,'autoload_with':engine2
#}
def __init__(self,**kw):
for k,v in kw.items():
setattr(self,k,v)
これはmodel.__init__.py
init モデル メソッドです (リフレクションが呼び出される場所):
def init_model(engine1,engine2):
"""Call me before using any of the tables or classes in the model."""
DBSession.configure(bind=engine1)
DBSession2.configure(bind=engine2)
# If you are using reflection to introspect your database and create
# table objects for you, your tables must be defined and mapped inside
# the init_model function, so that the engine is available if you
# use the model outside tg2, you need to make sure this is called before
# you use the model.
#
# See the following example:
metadata.bind = engine1
metadata2.bind = engine2
#metadata2=MetaData(engine2)
global t_reflected
#
t_reflected = Table("SOMETABLE", metadata2,
autoload=True, autoload_with=engine2)
#
mapper(Activities, t_reflected
だから私はsqlalchemyに主キーとは何かを伝える必要があると思います-しかし、リフレクションを使用しているときにそれを行うにはどうすればよいですか(主キーフィールドを知っています)?
作業ソリューションを編集します。
def init_model(engine1,engine2):
"""Call me before using any of the tables or classes in the model."""
DBSession.configure(bind=engine1)
DBSession2.configure(bind=engine2)
# If you are using reflection to introspect your database and create
# table objects for you, your tables must be defined and mapped inside
# the init_model function, so that the engine is available if you
# use the model outside tg2, you need to make sure this is called before
# you use the model.
#
# See the following example:
metadata.bind = engine1
metadata2.bind = engine2
#metadata2=MetaData(engine2)
global t_reflected
#
t_reflected = Table("SOMETABLE", metadata2,String,primary_key=True),
autoload=True, autoload_with=engine2)# adding the primary key column here didn't work
#
mapper(Activities, t_reflected, non_primary=True)# notice the needed non_primary - for some reason I can't do the whole mapping in one file and I Have to do part in init_model and part in the model - quite annoying
モデルでも、主キー列を追加する必要がありました。
class Activities(DeclarativeBase2):
__tablename__ = 'SOMETABLE'
#tried the classic way, I used in another place without tg but didn't work here - the reflection should be outside the class
EVENTCODE = Column(String, primary_key=True)# needed because the reflection couldn't find the primary key .
model.__init__.py
もちろん、これを機能させるには、さまざまなインポートを追加する必要もありました
奇妙なことに、データベースに接続する前に主キーが見つからないこと、およびスタンドアロンの sqlalchemy クラス (tg2 なし) が同じキーを実行しているときに、まったく文句を言わなかったことが判明しました。不思議に思う