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评论中的代码片段。
假设我有两个模型,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评论中的代码片段。