SQLAlchemy在一个优雅的查询中有三个多对多关系

时间:2017-07-12 16:29:33

标签: python sqlalchemy

如何通过三个多对多关系在sqlalchemy中进行查询,加入它们并获取唯一的记录?

我的设置如下:

  • 命令 - 用户可以执行的操作
  • 用户 - 群组 - 群组 用户轻松分发命令
  • UserGroup - N:N 用户和群组之间的关系
  • UserCommand - N:N关系 在用户和命令之间
  • GroupCommand - N:N之间的关系 组和命令

参见代码:

#!/usr/bin/python3
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import (
    Column,
    Integer,
    ForeignKey
)
from sqlalchemy.orm import (
    relationship,
    backref
)


Base = declarative_base()


class Command(Base):

    __tablename__ = 'commands'

    id = Column(Integer, primary_key=True)
    users = relationship('User', secondary='users_commands')
    groups = relationship('Group', secondary='groups_commands')


class User(Base):

    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    groups = relationship('Group', secondary='users_groups')
    commands = relationship('Command', secondary='users_commands')


class Group(Base):
    __tablename__ = 'groups'

    id = Column(Integer, primary_key=True)
    users = relationship('User', secondary='users_groups')
    commands = relationship('Command', secondary='groups_commands')


class UserGroup(Base):
    """Many-To-Many on users and groups"""

    __tablename__ = 'users_groups'

    user_id = Column(Integer, ForeignKey('users.id'), primary_key=True)
    group_id = Column(Integer, ForeignKey('groups.id'), primary_key=True)
    user = relationship('User', backref=backref('user_groups', cascade='all, delete-orphan'))
    user_group = relationship('UserGroup', backref=backref('user_groups', cascade='all, delete-orphan'))


class UserCommand(Base):
    """Many-to-many on users and commands"""

    __tablename__ = 'users_commands'

    user_id = Column(Integer, ForeignKey('users.id'), primary_key=True)
    command_id = Column(Integer, ForeignKey('commands.id'), primary_key=True)
    user = relationship('User', backref=backref('user_commands', cascade='all, delete-orphan'))
    command = relationship('Command', backref=backref('user_commands', cascade='all, delete-orphan'))


class GroupCommand(Base):
    """Many-to-many on groups and commands"""

    __tablename__ = 'groups_commands'

    group_id = Column(Integer, ForeignKey('groups.id'), primary_key=True)
    command_id = Column(Integer, ForeignKey('commands.id'), primary_key=True)
    group = relationship('Group', backref=backref('group_commands', cascade='all, delete-orphan'))
    command = relationship('Command', backref=backref('group_commands', cascade='all, delete-orphan'))

我希望为一个用户获取所有命令,首先是基于用户所在的组,然后是基于用户特定的命令。例如。伪代码:

  • 用户[1]属于集团[1,2]
  • 用户[1]本身有命令[1,2]
  • 组[1]有命令[2,3],组[2]有命令[3,4]
  • 我希望查询返回Command [1,2,3,4]

我可以通过两个单独的查询和列表/设置唯一连接来完成:

commands_user_specific = session.query(Command).\
                             join(Command.users).\
                             join(User.groups).\
                             filter(User.id == self.user.id).all()

commands_group_specific = session.query(Command).\
                              join(Command.groups).\
                              join(Group.users).\
                              filter(User.id == self.user.id).all()

commands = commands_user_specific +\
               list(set(commands_group_specific) - set(commands_user_specific))

但是我相信还有一些更优雅的方式,“。join”或者甚至通过“.filter”,我更喜欢使用它。

感谢您的见解

0 个答案:

没有答案