我为这个问题的标题感到挣扎,所以让我只列出代码:
档案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这样的低级文件中(并避免循环导入)
返回文件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()
所以,毕竟我的问题非常简单:有没有人知道更好/更惯用/更适合/不那么肮脏的感觉?
建议欢迎。
旁注
对于任何想知道的人:
“为什么不直接导入您想要引用加入/过滤操作的类?”
有几个原因导致您可能不希望/能够将类导入到编写查询的模块中。
答案 0 :(得分: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()
时,当此模块导入时您没有遇到任何问题,因为它实际上并没有尝试使用它导入的任何模块的内容。