Python sqlalchemy查询与sqlite的一对多关系

Python sqlalchemy查询与sqlite的一对多关系,python,sqlite,sqlalchemy,Python,Sqlite,Sqlalchemy,我已经编写了以下示例代码来为我正在编写的ACL系统构建搜索索引。本例中的查询将重新返回分配了任何给定ACL的所有对象。但我需要一个查询/过滤器,返回分配了所有ACL的对象 感谢您的帮助 #!/usr/bin/env python # -*- coding: utf-8 -*- from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship from sqlalchemy

我已经编写了以下示例代码来为我正在编写的ACL系统构建搜索索引。本例中的查询将重新返回分配了任何给定ACL的所有对象。但我需要一个查询/过滤器,返回分配了所有ACL的对象

感谢您的帮助

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import backref
from sqlalchemy import create_engine
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy import Column

_db_uri = "sqlite:////tmp/test.sql"
Base = declarative_base()
engine = create_engine(_db_uri, echo=False)
Session = sessionmaker(bind=engine)

class IndexObject(Base):
    """ Index object. """
    __tablename__ = 'objects'
    id = Column(Integer, primary_key=True)
    name = Column(String(128), unique=True, nullable=True)
    acls = relationship('IndexObjectACL',
                                cascade = "all,delete",
                                backref='objects',
                                lazy='dynamic')

    def __repr__(self):
        _repr_ =("<IndexObject (name='%s')>" % (self.name))
        return _repr_


class IndexObjectACL(Base):
    """ Index object ACL. """
    __tablename__ = 'acls'
    id = Column(Integer, primary_key=True)
    value = Column(String(128), nullable=False)
    oid = Column(Integer, ForeignKey('objects.id'))

    def __repr__(self):
        __repr__ = ("<IndexObjectACL (value='%s')>" % (self.value))
        return __repr__


object_list = [
        "object1",
        "object2",
        "object3",
    ]

acl_list = {
        "object1" : [
                    "view",
                    "edit",
                    "enable",
                    "delete",
                    ],
        "object2" : [
                    "view",
                    "edit",
                    ],
        "object3" : [
                    "enable",
                    "delete",
                    ],
    }


Base.metadata.create_all(engine)

session = Session()

for o in object_list:
    acls = []
    for acl in acl_list[o]:
        a = IndexObjectACL(value=acl)
        acls.append(a)

    index_object = IndexObject(name=o, acls=acls)
    session.add(index_object)

session.commit()


search_acls = [ "enable", "delete" ]
q = session.query(IndexObject)
q = q.join(IndexObject.acls).filter(IndexObjectACL.value.in_(search_acls))

print(q.all())

session.close()
#/usr/bin/env python
#-*-编码:utf-8-*-
从sqlalchemy.ext.declarative导入声明性基础
从sqlalchemy.orm导入关系
从sqlalchemy.orm导入sessionmaker
从sqlalchemy.orm导入backref
从sqlalchemy导入创建引擎
从sqlalchemy导入外键
从sqlalchemy导入整数
从sqlalchemy导入字符串
从sqlalchemy导入列
_db_uri=”sqlite:////tmp/test.sql"
Base=声明性_Base()
引擎=创建引擎(\u db\u uri,echo=False)
会话=会话生成器(绑定=引擎)
类索引对象(基):
“”“索引对象。”“”
__tablename_uu='objects'
id=列(整数,主键=True)
name=Column(字符串(128),unique=True,nullable=True)
ACL=关系('IndexObjectACL',
cascade=“全部,删除”,
backref='objects',
(动态的)
定义报告(自我):
_报告=(“”%(self.name))
返回报告_
类IndexObjectACL(基):
“”“索引对象ACL。”“”
__tablename_uu='acls'
id=列(整数,主键=True)
value=Column(字符串(128),null=False)
oid=列(整数,ForeignKey('objects.id'))
定义报告(自我):
__repr_uu=(“”%(self.value))
返回报告__
对象列表=[
“反对1”,
“反对2”,
“反对3”,
]
acl_列表={
“对象1”:[
“视图”,
“编辑”,
“启用”,
“删除”,
],
“目标2”:[
“视图”,
“编辑”,
],
“反对意见3”:[
“启用”,
“删除”,
],
}
Base.metadata.create_all(引擎)
会话=会话()
对于对象列表中的o:
acls=[]
对于acl_列表[o]中的acl:
a=索引对象acl(值=acl)
acls.append(a)
index_object=IndexObject(name=o,acls=acls)
session.add(索引\对象)
session.commit()
搜索\u acls=[“启用”,“删除”]
q=session.query(IndexObject)
q=q.join(IndexObject.acls).filter(IndexObjectACL.value.in(search\u acls))
打印(q.all())
session.close()

我认为这可能是一个使用的机会——从某种意义上说。IndexObjectACL除以SearchACL应生成包含所有SearchACL的IndexObject。换句话说,查询IndexObjectACL中不存在此类SearchACL的IndexObjects:

此查询的结果是

[<IndexObject (name='object1')>, <IndexObject (name='object3')>]
对于
acl_列表
(以及
object_列表
)的对象名称,它仍然只返回对象1和3,以证明未返回部分匹配

您的原始“have any”查询也可以重写为使用SQL语句中的或
EXISTS

q = session.query(IndexObject).\
    filter(IndexObject.acls.any(
        IndexObjectACL.value.in_(search_acls)))

我可以试着解释一下,但我对sqlalchemy和SQL一般来说是新手。所以我可能会用错误的方式解释。。。根据IndexObject和IndexObjectACL表之间的关系连接它们,从而生成一个新的查询。此查询用于为要使用的每个ACL创建新查询。最后,我们使用()获取所有查询中出现的所有IndexObject。经过一些测试后,这似乎是一种搜索已分配所有给定ACL的对象的快速方法。这也是一个非常类似于python的IMHO。

您的示例很有效,但我今天学习了intersect,并找到了另一个解决方案,我在下面发布了。不知道什么是最快的解决方案。但intersect版本更具可读性。无论如何,谢谢。这可能很有用,但如果有一些评论和解释,它会更有用。我添加了一个解释。如果有什么问题,请随时纠正我。
    "object4" : [
                "enable",
                ],
    "object5" : [
                "delete",
                ],
q = session.query(IndexObject).\
    filter(IndexObject.acls.any(
        IndexObjectACL.value.in_(search_acls)))
queries = []
acl_q = q.join(IndexObject.acls)
for acl in search_acls:
    x = acl_q.filter(IndexObjectACL.value == acl)
    queries.append(x)
q = q.intersect(*queries)