10

私はクラスを持っています:

class ExampleClass(Base):
    __tablename__ = 'chart'
    id = Column(Integer, primary_key=True)
    element_id = Column(Integer, ForeignKey('anotherTable.id'))
    element = relationship(AnotherClass)
    element2_id = Column(Integer, ForeignKey('anotherTable2.id'))
    element2 = relationship(AnotherClass2)

element_idandに基づいてルックアップを行いたいelement2_id:

class ExampleClass(Base):
    ...
    def get_with_element2(self, element2):
        return session.query(ExampleClass).\
                       filter_by(element_id = self.element_id,
                                 element2_id = element2.id).first()

私が見つけた問題は、新しいExampleClassオブジェクトをインスタンス化してそれに割り当てるとelementelement_idフィールドが設定されないことです:

a = ExampleClass(element=element_obj)
a.element_id => None

どうすればこれを解決できますか? このような状況に対処する最善の方法は何ですか?

4

1 に答える 1

12

まず、以下のすべての例では、インスタンスが「永続的」状態 (つまり、) ではないExampleClassにしても、少なくとも保留session.add(a)状態にあると想定しています。つまり、まだ を操作しSessionておらず、オブジェクトを に追加していないExampleClass場合、 のデータベース レベルの動作は得られず、relationship()外部キー列の値を維持することが主な機能です。もちろん、この割り当てを直接行うことは自由です。

a = ExampleClass(element_id=element_obj.id)

しかし、これは明らかに、relationship()構造によって提供される自動化を利用していません。

による外部キー属性の割り当ては、フラッシュrelationship()中に発生します。これは、 を使用して SQL ステートメントを発行する前、または を使用してトランザクションを完了する前など、データベースとの対話が必要な場合にのみ発生するプロセスです。session.query()session.commit()

一般に、relationship()ここでは "element" 属性と "element2" 属性のみを処理し、外部キー属性はバックグラウンドで処理するというのが の哲学です。次のようにクエリを記述できます。

session.query(ExampleClass).\
     filter_by(element=self.element).\
     filter_by(element2=element2)

ORM は のような比較をSomeClass.somerelationship=someobject行い、それを外部キー式に変換しますSomeClass.some_fk=some_idが、違いは、「some_id」の最終的な値の評価が、クエリが実行される直前まで延期されることです。クエリが実行される前に、Query()オブジェクトはSession「autoflush」を指示します。これにより、オブジェクトの属性に割り当てられているExampleClass主キー識別子とともに行が挿入されます。element_objelement_idExampleClass

このように FK アトリビュートを使用しながら、同様の効果を得ることができます。

session.query(ExampleClass).\
   filter_by(element_id=bindparam(callable_=lambda: self.element_id)).\
   filter_by(element2_id=element2.id)

またはさらに明示的に、最初にフラッシュを実行します。

session.flush()
session.query(ExampleClass).\
   filter_by(element_id=self.element_id).\
   filter_by(element2_id=element2.id)

そのため、外部キー属性を明示的に参照したい程度にelement_id応じて、明示的に行うことも必要になりrelationship()ます。オブジェクト インスタンスとrelationship()-bound 属性を厳密に扱いautoflush、有効などの一般的なデフォルトのままにしておくと、通常は「正しいこと」が行われ、必要なときに属性が準備できるようになります。

于 2012-12-25T15:52:37.460 に答える