SQLAlchemy:如何在不导入模型的情况下过滤连接的 table

SQLAlchemy: How to filter on a joined table without importing the model

假设我有两个模型,ModelA 和 ModelB。

它们通过 1:n 关系联系在一起,例如ModelA 可以关联多个 ModelB。一个正常的 relationship() 是在 SQLalchemy 中定义的,这通常工作得很好。当我需要做一些更复杂的查询时,就会出现问题。比方说,我想 return 所有 ModelB 条目,其中关联的 ModelA 条目具有特定属性。到目前为止我所做的是:

return db.query(ModelB)\
            .filter(
                ModelB.user_id == user_id,
                ModelB.accepted == True
            )\
            .join(ModelB.modela_relationship)\
            .filter(
                ModelB.modela_relationship.attribute1 == some_value,
                ModelB.modela_relationship.date > datetime.now()
            )\
            .all()

我明确希望使用这种形式的关系连接,而不是定义 aliased 模型,因为我需要导入其他模型才能正常工作。我不想导入模型的原因是这会导致循环导入,因为 ModelA 需要 ModelB 进行查询,而 ModelB 需要 ModelA。

上面的代码会产生错误,内容为:

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with ModelB.modela_relationship has an attribute 'attribute1'

我如何在不需要在 SQLalchemy 中导入模型的情况下执行此查询(获取所有结果按连接值过滤)?

从我的评论开始:

如果您迫切希望将函数作为模式的方法,您可以做一些更复杂的事情,即将 ModelA 和 ModelB 都导入到一个新文件中,然后从模型继承到一个新定义中像这样:

from .filea import ModelA
from .fileb import ModelB
from . import db

class ModelBExtra(ModelB):
  __mapper_args__ = {
      "polymorphic_identity": "model_b_extra"
  }

  def myfunc(self):
    return db.query(ModelB).join(
              ModelB.modela_relationship
            ).filter(
                ModelB.user_id == user_id,
                ModelB.accepted == True,
                ModelA.attribute1 == some_value,
                ModelA.date > datetime.now()
            ).all()

它为您提供了基本相同的方法 table,您只需将其导入到您需要的地方即可。 https://docs.sqlalchemy.org/en/14/orm/inheritance.html

请注意,这在 SQL 数据库 'model_b' 中使用相同的底层 table。它只是以不同的名称向 SQLAlchemy 声明,因为 SQLAlchemy 不能有具有相同名称的模式定义。我喜欢偶尔使用它来将代码和方法划分到只需要它们的地方,并像我在评论中提到的那样只在一个方向上维护导入链。

我知道这并不是对确切问题的真正答案,但我不能post评论中的代码片段。