Python SQLAlchemy M2M关系查询

Python SQLAlchemy M2M关系查询,python,sqlalchemy,Python,Sqlalchemy,我有以下模型,我正在尝试列出所有最新的DocumentVersions,它们在用户组中有一个组 class User(Base, BaseModel): __tablename__ = 'users' id = Column(Integer, primary_key=True) email = Column(Unicode(EMAIL_LENGTH), unique=True, nullable=False) full_name = Column(Unicode(

我有以下模型,我正在尝试列出所有最新的DocumentVersions,它们在用户组中有一个组

class User(Base, BaseModel):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    email = Column(Unicode(EMAIL_LENGTH), unique=True, nullable=False)
    full_name = Column(Unicode(FULL_NAME_LENGTH), nullable=False)
    deleted = Column(Boolean, nullable=False, default=False)

    document_versions = relationship(
        'DocumentVersion', 
        backref="author")


class Group(Base, BaseModel):
    __tablename__ = 'groups'
    __table_args__ = (UniqueConstraint('name','company_id'),)
    id = Column(Integer, primary_key=True)
    name = Column(Unicode(60), nullable=False)
    deleted = Column(Boolean, nullable=False, default=False)

    # Companies have many groups
    company_id = Column(
            Integer,
            ForeignKey('companies.id'),
            nullable=False)
    roles = relationship("Role",
            primaryjoin="Group.id==Role.group_id",
            backref="group")
    users = relationship("User",
            secondary=group_user,
            backref="groups")

document_version_group = Table(
        "document_version_groups",
        Base.metadata,
        Column('group_id', Integer, ForeignKey('groups.id')),
        Column('document_version_id', Integer, ForeignKey('document_versions.id')))

class DocumentVersion(Base, BaseModel):
    __tablename__ = 'document_versions'
    id = Column(Integer, primary_key=True)
    document_id = Column(
            Integer,
            ForeignKey('documents.id'),
            nullable=False)

    author_id = Column(
            Integer,
            ForeignKey('users.id'),
            nullable=False)
    groups = relationship(
            "Group",
            secondary=document_version_group,
            lazy='dynamic', # This is newly added just now
            backref="document_versions")
    status = Column(
            Enum(
                "draft",
                "review",
                "approval",
                "declined",
                "approved",
                name="status"),
            default="draft",
            nullable=False)
我尝试了以下方法,但没有成功(请注意,返回的文档\u版本没有组)

>>docs=session.query(DocumentVersion).filter(Document.company==user.company).filter(Group.id.in_uuz([g.id代表g in user.groups])).all()
2012-08-31 15:14:19651信息[sqlalchemy.engine.base.engine][main thread]选择document_versions.id作为document_versions_id,document_versions.document_id作为document_versions_document_id,document_versions.document_current_草稿_id作为document_versions_current_草稿_id,文档\u版本。文档\u当前\u活动\u id作为文档\u版本\u当前\u活动\u id,文档\u版本。作者\u id作为文档\u版本\u作者\u id,文档\u版本。状态作为文档\u版本\u状态,文档\u版本。主要版本作为文档\u版本\u主要版本,文档\u版本。次要版本作为文档\u版本\u次要版本
来自文档\u版本、文档、组
其中%(参数1)s=documents.company_id和groups.id IN(%(id_1)s)
2012-08-31 15:14:19651信息[sqlalchemy.engine.base.engine][MainThread]{'id_1':1,'param_1':1}
>>>[d.groups.all()表示文档中的d]
2012-08-31 15:15:29996信息[sqlalchemy.engine.base.engine][main]选择groups.id作为groups\u id,groups.name作为groups\u name,groups.deleted作为groups\u deleted,groups.company\u id作为groups\u company\u id
从组、文档\u版本\u组
其中%(参数1)s=文档版本组。文档版本组id和组。id=文档版本组。组id
2012-08-31 15:15:29996信息[sqlalchemy.engine.base.engine][MainThread]{'param_1':1}
2012-08-31 15:15:29998信息[sqlalchemy.engine.base.engine][MainThread]选择groups.id作为groups\u id,groups.name作为groups\u name,groups.deleted作为groups\u deleted,groups.company\u id作为groups\u company\u id
从组、文档\u版本\u组
其中%(参数1)s=文档版本组。文档版本组id和组。id=文档版本组。组id
2012-08-31 15:15:29998信息[sqlalchemy.engine.base.engine][MainThread]{'param_1':2}
[[], []]

假设此SQL给出正确的结果:

SELECT *
FROM document_versions
WHERE
    EXISTS (
        SELECT 1
        FROM documents
        WHERE
            document_versions.document_id = documents.id
            AND documents.company_id = :company_id
    )
    AND EXISTS (
        SELECT 1
        FROM document_version_groups
        WHERE
            document_versions.id = document_version_groups.document_version_id
            AND document_version_groups.group_id IN :group_ids
    )
那么以下SQLAlchemy表达式应该可以工作:

session.query(DocumentVersion).filter(and_(
    DocumentVersion.document.has(compay=user.company),
    DocumentVersion.groups.any(
        Group.id.in_([g.id for g in user.groups])
    ),
)).all()
请注意关系属性
DocumentVersion.document
DocumentVersion.groups
的明确使用。如果没有它们,查询将只由一堆不相关的表组成,从而得到假阳性结果

session.query(DocumentVersion).filter(and_(
    DocumentVersion.document.has(compay=user.company),
    DocumentVersion.groups.any(
        Group.id.in_([g.id for g in user.groups])
    ),
)).all()