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())