在关系的attribute_mapped_collection字段上过滤SQLAlchemy查询

时间:2013-11-12 03:49:30

标签: python sqlalchemy

我有两个类,标签和硬件,用简单的父子关系定义(参见最后的完整定义)。

现在我想通过attribute_mapped_collection使用Hardware中的version字段过滤Tag上的查询,例如:

def get_tags(order_code=None, hardware_filters=None):
    session = Session()
    query = session.query(Tag)
    if order_code:
        query = query.filter(Tag.order_code == order_code)
    if hardware_filters:
        for k, v in hardware_filters.iteritems():
            query = query.filter(getattr(Tag.hardware, k).version == v)
    return query.all()

但我明白了:

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Tag.hardware has an attribute 'baseband

如果我通过对属性进行硬编码将其剥离,例如:

,就会发生同样的事情

query.filter(Tag.hardware.baseband.version == v)

我可以这样做:

query = query.filter(Tag.hardware.any(artefact=k, version=v))

但为什么我不能直接通过属性过滤?

课程定义

class Tag(Base):
    __tablename__ = 'tag'
    tag_id = Column(Integer, primary_key=True)
    order_code = Column(String, nullable=False)
    version = Column(String, nullable=False)
    status = Column(String, nullable=False)
    comments = Column(String)
    hardware = relationship(
        "Hardware",
        backref="tag",
        collection_class=attribute_mapped_collection('artefact'),
    )
    __table_args__ = (
        UniqueConstraint('order_code', 'version'),
    )

class Hardware(Base):
    __tablename__ = 'hardware'
    hardware_id = Column(Integer, primary_key=True)
    tag_id = Column(String, ForeignKey('tag.tag_id'))
    product_id = Column(String, nullable=True)
    artefact = Column(String, nullable=False)
    version = Column(String, nullable=False)

1 个答案:

答案 0 :(得分:1)

撰写查询时,我们最终会编写SQL。您认为从filter(Tag.hardware.baseband)这样的表达式呈现的SQL是什么?对此没有简单的答案,SQLAlchemy从未对如何沿着多条路径遍历这样的工作做出任何猜测。 attribute_mapped_collection的用法仅与Python中的对象操作相关,并且对此属性的SQL呈现方式没有影响。因此,您需要使用直接映射到SQL的构造,在这种情况下,ANY()似乎是一个不错的选择。