1

我为这个问题的标题而苦苦挣扎,所以让我列出代码:

档案一:

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(并避免循环导入)

返回文件 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()时你没有任何问题,因为它实际上并没有尝试使用它导入的任何模块的内容。

于 2013-05-12T02:06:14.357 回答