通过键/值对查询SQLAlchemy中的dict集合

时间:2016-08-07 14:14:18

标签: python sqlalchemy

我有一个SQLAlchemy模型,它将标记(键/值对)与元素相关联,如下所示:

from sqlalchemy import create_engine, Column, ForeignKey, Integer, Unicode
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import backref, relationship, sessionmaker
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm.collections import attribute_mapped_collection

engine = create_engine("sqlite:///:memory:")
base = declarative_base(bind=engine)

class Tag(base):
    __tablename__ = "tags"

    tag_id = Column(Integer, primary_key=True)

    key = Column(Unicode(256))
    value = Column(Unicode(256))

    def __init__(self, key="", value="", **kwargs):
        self.key = key
        self.value = value
        base.__init__(self, **kwargs)

class Element(base):
    __tablename__ = "elements"

    element_id = Column(Integer, primary_key=True)
    tags = association_proxy("elements_tags", "tag_value",
                             creator=lambda k, v: ElementsTags(tag_key=k, tag_value=v))

class ElementsTags(base):
    __tablename__ = "elements_tags"

    map_id = Column(Integer, primary_key=True)

    element_id = Column(Integer, ForeignKey('elements.element_id'))
    tag_id = Column(Integer, ForeignKey('tags.tag_id'))

    element = relationship(Element, foreign_keys=[element_id],
                           backref=backref("elements_tags",
                                           collection_class=attribute_mapped_collection("tag_key"),
                                           cascade="all, delete-orphan"))

    tag = relationship(Tag, foreign_keys=[tag_id])
    tag_key = association_proxy("tag", "key")
    tag_value = association_proxy("tag", "value")

base.metadata.create_all()

Element.tags是一个字典集合,有一些代理使它看起来就像一个简单的字典,效果非常好:

session = sessionmaker(bind=engine)()

element = Element()
element.tags = {u"foo": u"bar", u"bang": u"baz"}

session.add(element)
session.commit()

现在,我如何使用Element将所有具有某个键/值对的session.query(Element)作为标记附加?

我找到了this documentation,我从中session.query(Element).filter(Element.tags.has(key="foo", value="bar")).all()推导出https://docs.arangodb.com/3.0/HTTP/Collection/Creating.html#create-collection。然而,这引发了:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/ext/associationproxy.py", line 409, in has
    if self._target_is_object:
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/util/langhelpers.py", line 754, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/ext/associationproxy.py", line 244, in _target_is_object
    return getattr(self.target_class, self.value_attr).impl.uses_objects
AttributeError: 'AssociationProxy' object has no attribute 'impl'

1 个答案:

答案 0 :(得分:0)

不幸的是,SQLAlchemy中尚不支持此类查询,最高可达1.1.0~b3。必须通过连接通过关联代理链接的表来手动构造查询。

支持将在未来版本中出现,并且已有补丁:https://bitbucket.org/zzzeek/sqlalchemy/issues/3769/chained-any-has-with-association-proxy

将支持修补到当前的SQLAlchemy版本中也很简单:https://github.com/Natureshadow/OSMAlchemy/blob/master/osmalchemy/util/patch.py

相关问题