Python Sqlalchemy与关系过滤
从下面的代码中,我定义了如下关系:Python Sqlalchemy与关系过滤,python,filter,sqlalchemy,relationship,Python,Filter,Sqlalchemy,Relationship,从下面的代码中,我定义了如下关系: UnitTypeRowModel (self-referencing but only one in the doc) -- PlanPmDefinition (definition in the json doc) -- PlanPmValues (value in the json doc) 如果数据库表中只有一个plan_ou,则当前结果为json: 代码: 如何从方法UnitTypeRowModel.get\u for\u unit中的类
UnitTypeRowModel (self-referencing but only one in the doc)
-- PlanPmDefinition (definition in the json doc)
-- PlanPmValues (value in the json doc)
如果数据库表中只有一个plan_ou,则当前结果为json:
代码:
如何从方法UnitTypeRowModel.get\u for\u unit中的类PlanPmValues中筛选plan\u?对此,应使用自定义ColumnProperty
from sqlalchemy import select, and_
from sqlalchemy.orm import column_property
class UnitTypeRowModel(Base):
...
_ou_join = and_(plan_pm_id==PlanPmDefinition.id,
PlanPmDefinition.tag==PlanPmValues.tag,
plan_pm_id==PlanPmValues.plan_pm_id)
plan_ou = column_property(select([PlanPmValues.plan_ou],
whereclause=_ou_join).as_scalar())
我已经打破了作为一个单独的属性加入,只是为了可读性
按照在SQLAlchemy代码中定义的方式,UnitTypeRowModel和PlanpDefinition之间存在多对一关系;PlanpDefinition和PlanpValue之间存在多对一关系。我从这两个关系调用的uselist=False参数推断,如果您没有通过使用唯一键在数据库中强制执行,您可能会遇到其他一些错误。这意味着结果值只能返回一行,这是我用as_scalar强制执行的
通常,您可以使用以下命令处理相关对象上的查询:。在这种情况下,这并不理想,因为UnitTypeRowModel和PlanpValue之间已经存在和关联对象PlanpDefinition;这意味着关联_代理将允许您直接从UnitTypeRowModel类处理PlanpValue对象,而不是处理plan_值
最后,您应该始终验证是否需要作为SQLAlchemy Query.filter执行此操作——也就是说,在SQL server上执行查询和筛选,而不是在Python中通过filter执行查询和筛选。前者需要更多的时间来编码和测试,但几乎总是更快,因为SQL Server为此进行了优化;后者需要更少的时间来编写代码,实际上,当您执行大量返回大量结果的查询时,只会导致性能问题。就我个人而言,我用Python编写东西,然后通过SQL执行缓慢的查询。实际上应该是一对一的查询。我应该省略标记或将其添加到联接中,因为它实际上始终为0,没有使用,但不是我自己做的。我已经更新了问题,希望不要使用多对一。我也不想要一个子查询,而是一个直接的左外连接,其中必须在join子句上设置plan\u ou,而不是在where的底部。我将进一步查看association\u proxy。要获得无子查询的直接联接,可以将UnitTypeRowModel映射到3表联接。事实上,您已经在每次查询UnitTypeRowModel时都进行了连接,因为您的关系中有lazy=join关键字。如果您想从UnitTypeRowModel类强制执行只读访问,我认为您必须通过python属性来运行它们,以防止容易编写。如果您想查看其中任何一个的代码,请告诉我,我会更新答案。是的,我会按照我的意愿获取所有代码,但我想要的是在查询时从PlanpValues联接中为plan_ou添加一个过滤器。
class PlanPmValues(Base):
__tablename__ = 'plan_pm_municipal_values'
plan_pm_id = Column(Integer, primary_key=True)
tag = Column(Integer, primary_key=True)
plan_ou = Column(Integer) # Filter on this
...
class PlanPmDefinition(Base):
__tablename__ = 'plan_pm_municipal_definition'
id = Column(Integer, primary_key=True)
tag = Column(Integer, primary_key=True) -- always 0
value = relationship(PlanPmValues,
primaryjoin='and_(PlanPmDefinition.id==PlanPmValues.plan_pm_id, ' +
'PlanPmDefinition.tag==PlanPmValues.tag)',
foreign_keys='[PlanPmValues.plan_pm_id, PlanPmValues.tag]',
lazy='joined', uselist=False)
class UnitTypeRowModel(Base):
__tablename__ = 'unit_type_row_model'
__table_args__ = {'schema': base_schema}
id = Column(Integer, primary_key=True)
client_id = Column(Integer, ForeignKey(base_schema + '.client.id'))
parent_id = Column(Integer, ForeignKey(base_schema + '.unit_type_row_model.id'), nullable=True)
plan_pm_id = Column(Integer, nullable=True)
children = relationship(
'UnitTypeRowModel',
lazy='joined',
join_depth=2,
order_by="UnitTypeRowModel.sort_order")
definition = relationship(
'PlanPmDefinition',
primaryjoin='and_(PlanPmDefinition.id==UnitTypeRowModel.plan_pm_id, ' +
'PlanPmDefinition.tag==0)',
foreign_keys='[UnitTypeRowModel.plan_pm_id]',
lazy='joined',
uselist=False)
@staticmethod
def get_for_unit(client_id, unit_id):
db_session = DatabaseEngine.get_session()
row_models = db_session.query(UnitTypeRowModel).\
filter(UnitTypeRowModel.client_id == client_id).\
order_by(UnitTypeRowModel.sort_order)
json = util.Serialize.serialize_to_json(row_models)
db_session.close()
return json
from sqlalchemy import select, and_
from sqlalchemy.orm import column_property
class UnitTypeRowModel(Base):
...
_ou_join = and_(plan_pm_id==PlanPmDefinition.id,
PlanPmDefinition.tag==PlanPmValues.tag,
plan_pm_id==PlanPmValues.plan_pm_id)
plan_ou = column_property(select([PlanPmValues.plan_ou],
whereclause=_ou_join).as_scalar())