2012-01-09 9 views
2

Iは第一bzCheckによって関連付けられている2つのテーブル、testInstanceとのBugzillaを持っを関連付けるオブジェクトを追加:このように、2つの既存のオブジェクト

class Instance(Base): 
    __tablename__ = "testInstance" 

    id = Column(Integer, primary_key=True) 

    bz_checks = relation(BZCheck, backref="instance") 

class BZCheck(Base): 
    __tablename__ = "bzCheck" 

    instance_id = Column(Integer, ForeignKey("testInstance.id"), primary_key=True) 
    bz_id = Column(Integer, ForeignKey("bugzilla.id"), primary_key=True) 
    status = Column(String, nullable=False) 

    bug = relation(Bugzilla, backref="checks") 

class Bugzilla(Base): 
    __tablename__ = "bugzilla" 

    id = Column(Integer, primary_key=True) 

バックエンドがPostgreSQLサーバです。私はSQLAlchemyの0.5を使用してい

私はインスタンス、BugzillaのとBZCheck ojectsを作成する場合は、その後、

bzcheck.bug = bugzilla 
instance.bz_checks.append(bzcheck) 

と追加し、それらをコミットしません。すべて順調。

instance = session.query(Instance).filter(Instance.id == 31).one() 
bugzilla = session.query(Bugzilla).filter(Bugzilla.id == 19876).one() 
check = BZCheck(status="OK") 
check.bug = bugzilla 
instance.bz_checks.append(check) 

それは失敗します:

In [6]: instance.bz_checks.append(check) 
2012-01-09 18:43:50,713 INFO sqlalchemy.engine.base.Engine.0x...3bd0 select nextval('"bzCheck_instance_id_seq"') 
2012-01-09 18:43:50,713 INFO sqlalchemy.engine.base.Engine.0x...3bd0 None 
2012-01-09 18:43:50,713 INFO sqlalchemy.engine.base.Engine.0x...3bd0 ROLLBACK 

はそれから新しいIDを取得しようと

しかし、今、のは、私は既存のインスタンスおよび既存のBugzillaを持っており、それらを関連付けたいとしましょう外部キー "testInstance.id"を使用する代わりに、わかりにくいシーケンス...理由を理解できません。 オブジェクトをコミットした後にオブジェクトを修正しようとしたときに同様の問題が発生しました。基本的なものを見逃していたはずですが、何がありますか?

+0

なぜ最新のバージョン、0.7を使用していませんか? –

+0

最終的に使用されるマシンは0.5.8しかないディストリビューションを実行しているので、私は手動インストールを避けたい – deubeuliou

答えて

2

ここで欠落している部分はスタックトレースです。常にスタックトレースを見て - 何ここで重要なことは、それはinstance.bz_checksのアクセスによって生成自動フラッシュ、ということです。

Traceback (most recent call last): 
    File "test.py", line 44, in <module> 
    instance.bz_checks.append(check) 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/attributes.py", line 168, in __get__ 
    return self.impl.get(instance_state(instance),dict_) 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/attributes.py", line 453, in get 
    value = self.callable_(state, passive) 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/strategies.py", line 563, in _load_for_state 
    result = q.all() 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/query.py", line 1983, in all 
    return list(self) 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/query.py", line 2092, in __iter__ 
    self.session._autoflush() 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/session.py", line 973, in _autoflush 
    self.flush() 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/session.py", line 1547, in flush 
    self._flush(objects) 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/session.py", line 1616, in _flush 
    flush_context.execute() 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/unitofwork.py", line 328, in execute 
    rec.execute(self) 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/unitofwork.py", line 472, in execute 
    uow 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/mapper.py", line 2291, in _save_obj 
    execute(statement, params) 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/engine/base.py", line 1405, in execute 
    params) 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/engine/base.py", line 1538, in _execute_clauseelement 
    compiled_sql, distilled_params 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/engine/base.py", line 1646, in _execute_context 
    context) 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/engine/base.py", line 1639, in _execute_context 
    context) 
    File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/engine/default.py", line 330, in do_execute 
    cursor.execute(statement, parameters) 
sqlalchemy.exc.IntegrityError: (IntegrityError) null value in column "instance_id" violates not-null constraint 
'INSERT INTO "bzCheck" (bz_id, status) VALUES (%(bz_id)s, %(status)s) RETURNING "bzCheck".instance_id' {'status': 'OK', 'bz_id': 19876} 

コードの行があるので、あなたがこれを見ることができます。その後、

instance.bz_checks.append(check) 

自動フラッシュ:

self.session._autoflush() 
File "/Users/classic/dev/sqlalchemy/lib/sqlalchemy/orm/session.py", line 973, in _autoflush 

三のソリューション:

aa。オートフラッシュを一時的に無効にする(http://www.sqlalchemy.org/trac/wiki/UsageRecipes/DisableAutoflush参照)

b。

BZState(バグ= bugzillaを、インスタンス=インスタンス)(これは協会のために良いアイデアはオブジェクト通常である - 彼らは:それはどのコレクションにアクセスする前に必要な完全な状態だとBZCheck関連オブジェクトは常に作成されていることを確認2つの点の間の関連を表すので、この状態でインスタンス化することが最も適切です)

c。 check.bug = somebugの操作が実際にはのセッションにcheckを配置しないように、カスケード規則を変更してください。 cascade_backrefsでこれを行うことができます(http://www.sqlalchemy.org/docs/orm/session.html#controlling-cascade-on-backrefsで説明)。 (ただし、0.6または0.7にする必要があります)

+0

autoflushを無効にしてくれました。ありがとうございました。私は後で解決策Bを覚えておきます。 – deubeuliou

関連する問題