从下面的代码我已经定义了这样的关系:
UnitTypeRowModel (self-referencing but only one in the doc)
-- PlanPmDefinition (definition in the json doc)
-- PlanPmValues (value in the json doc)
如果我在数据库表中只有一个plan_ou,则当前结果为json:
[{
"children": [],
"parent_id": 1,
"id": 4
}, {
"children": [],
"parent_id": 2,
"plan_pm_id": 2,
"id": 5
"definition": {
"id": 2,
"tag": 0,
"value": {
"plan_pm_id": 2,
"tag": 0,
"plan_ou": 1
}
}
}]
代码:
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
如何在方法plan_ou
中对课程PlanPmValues
中的UnitTypeRowModel.get_for_unit
进行过滤?
答案 0 :(得分:0)
您应该使用自定义ColumnPropery
。
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())
为了便于阅读,我将_ou_join
作为单独的属性打破了。
您在SQLAlchemy代码中定义的方式,UnitTypeRowModel
和PlanPmDefinition
之间存在多对一关系;并且PlanPmDefinition
和PlanPmValues
之间存在多对一关系。我在uselist=False
个参数中推断这两个relationship()
调用,如果你没有通过使用唯一键在数据库中强制执行,那么你可能会遇到其他一些错误。这意味着结果值只能返回一行,我已使用as_scalar()
强制执行。
通常,您使用association_proxy()
处理对此类相关对象的查询。在这种情况下,这并不理想,因为您已在PlanPmDefinition
和UnitTypeRowModel
之间拥有和关联对象(PlanPmValues
);这意味着association_proxy
将允许您直接从PlanPmValue
类处理UnitTypeRowModel
个对象,而不是plan_ou
值。
最后,您应该始终验证您需要以SQLAlchemy Query.filter()
的身份执行此操作 - 即在SQL服务器上执行查询和筛选 - 而不是执行此操作在Python中通过filter()
。前者需要更多时间进行编码和测试,但几乎总是会更快,因为SQL服务器已针对它进行了优化;后者花费较少的代码时间,实际上只会在执行大量返回大量结果的查询时导致性能问题。我个人用Python编写内容,然后通过SQL进行慢速查询。