1

この質問のタイトルに苦労したので、コードをレイアウトしましょう。

ファイル A:

class SomeClass(Base):
    __tablename__ = 'some_classes'
    id = Column(Integer, primary_key=True)
    my_awesome_property = Column(Unicode(255))
    other_class = relationship('OtherClass', backref='some_class', uselist=False)

ファイル B:

class OtherClass(Base):
    __tablename__ = 'other_classes'
    id = Column(Integer, primary_key=True)
    my_sweet_property = Column(Unicode(255))
    some_class_id = Column(ForeignKey('some_classes.id'))

さて、多くの場合、次のようないくつかの関数を含む「高次」ファイルからこれらのファイルの両方を参照します。

高次ファイル:

from model.alpha import SomeClass
from model.bravo import OtherClass
from sqlalchemy.orm import sessionmaker

session = sessionmaker(bind=some_engine)()

def some_random_query():
    return session.query(SomeClass).join(OtherClass).filter(OtherClass.my_sweet_property=='Mike Bayer\'s cat speaks SQL.').first()

それはごく普通のことで、何も問題はありません...まで...ファイルAのような下位レベルのファイルの1つに関数を配置することにしました(そして循環インポートを避けます)

ファイル A に戻る:

# pretend I imported a session here
def frustrating_situation():
     session.query(SomeClass).join(SomeClass.other_class).filter(SomeClass.other_class.my_sweet_property=='Get ready for an exception!').first()

これにより、この悪い男の子がここにスローされます。

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with SomeClass.other_class has an attribute 'my_sweet_property'

SQLAlchemy の内部構造について私が知っていることを考えると、これは理にかなっていると思いますが、API の観点からも、ステートメントは実際に機能するはずだと思います。

これが私がそれを回避した方法です:

session.query(SomeClass).join(SomeClass.other_class).filter(SomeClass.other_class.property.mapper.c.my_sweet_property == 'verbose, yet it works as desired').first()

結局のところ、私の質問は非常に単純です。これを行うための、より良い/より慣用的な/適切な/より汚い感じのない方法を知っている人はいますか?

提案を歓迎します。

サイドノート

疑問に思っている人のために:

「結合/フィルター操作のために参照したいクラスをインポートするだけではどうですか?」

クエリを記述しているモジュールにクラスをインポートしたくない/できない理由はいくつかあります。

  • クラス定義を多くのファイルに分割し、同じレベルのモジュール間で厳密にインポートしないことで循環インポートを回避することにしました
  • 現在定義されていない、または現在のモジュールにインポートされていない 1 つ以上のクラスで動作する関数を配置することを決定しましたが、それらはモジュール内で他の理由で使用されていないため、インポートしたくありません (理由 1 をもう一度参照してください)。
4

1 に答える 1

1
SomeClass.other_class.my_sweet_property

sqlalchemy では機能しません。ごめん。

OtherClassこの.filter()句では、を参照しています。どのようにその名前にたどり着くかはあなた次第ですが、各ステートメントが何を意味し、議論がどこから来るかという観点から見ると、最も明確な方法は、単に物事をインポートすることです。

編集: 循環インポートの問題の一般的な原因は、モジュールをインポートするだけでなく、モジュールから名前を直接インポートしようとしたときに発生します。次のようなコードを回すと:

from foo import Bar
def baz():
    Bar.quux()

foo もこのモジュールをインポートしようとすると、インポートの問題が発生します (たとえば、baz を使用したいため)。

モジュールのみをインポートして修正します。

import foo
def baz()
    foo.Bar.quux()

foo.Barは後で解決されるため、 が呼び出されたときにのみ、このbaz()モジュールが import されたときに問題はありません。これは、インポートしたモジュールの内容を実際に使用しようとしないためです。

于 2013-05-12T02:06:14.357 に答える