文章内容

2021/5/6 19:40:06,作 者: 黄兵

SQLAlchemy 多对多如何查询

下面有一个模型是根据多对多建立的,具体代码如下:

user_groups = Table('user_groups', Base.metadata,
    Column('user_id', String(128), ForeignKey('users.username')),
    Column('group_id', Integer, ForeignKey('groups.id'))
)

class ZKUser(Base, ZKTableAudit):
    __tablename__ = 'users'

    username   = Column(String(128), primary_key=True)
    first_name = Column(String(512))
    last_name  = Column(String(512))

    groups = relationship(ZKGroup, secondary=user_groups, backref='users')

class ZKGroup(Base, ZKTableAudit):
    __tablename__ = 'groups'

    id          = Column(Integer, primary_key=True)
    name        = Column(String(512))

对于多对多模型应该如何查询,下面是具体查询示例:

session.query(ZKUser).filter(ZKUser.groups.any(ZKGroup.id.in_([1,2,3])))

生成的SQL代码如下:

SELECT * FROM users 
WHERE EXISTS (
    SELECT 1 FROM user_groups, groups 
    WHERE users.id = user_groups.contact_id 
        AND groups.id = user_groups.group_id 
        AND groups.id IN (%s, %s, %s)
    )

也可以通过连接的查询方式,代码如下:

users = (
    session.query(ZKUser)
    .join(user_groups)
    .filter(user_groups.columns.group_id.in_([1, 2, 3]))
)

生成的SQL代码如下:

SELECT *
FROM users
JOIN user_groups ON users.id = user_groups.user_id 
WHERE user_groups.group_id IN (1, 2, 3)

我更喜欢下面一种方式,直观,并且通过join连接,也更合理一些。


参考资料:

1、SQLAlchemy: filter by membership in at least one many-to-many related table

Python CIDR IP Range
Python python-dotenv
分享到:

发表评论

评论列表