sqlalchemy表关系之多对多

本文介绍使用Python的SQLAlchemy库实现表间多对多关系的方法。通过定义中间表及模型类之间的relationship属性,实现Arctire与Tag模型间的多对多关联。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

sqlalchemy表之间的关系有三种:1、多对多  2、一对多  3、一对一
下面就讲讲sqlalchemy表之间如何建立多对多关系。 
首先,我们把两个需要做多对多关系的模型定义出来,这里以Arctire,Tag模型为例(示例代码如下)
class Arctire(Base): 
     __tablename__ = "arctire"  
  id = Column(Integer , primary_key=True , autoincrement=True)  
  name = Column(String(50) , nullable=False)  
  tags = relationship("Tag", backref="arctires", secondary=arctire_tag)
  
def __repr__(self):
  return "name:%s"%self.name
  
class Tag(Base):  
   __tablename__ = "tag"  
  id = Column(Integer , primary_key=True , autoincrement=True)  
  tag = Column(String(50) , nullable=False)
  
def __repr__(self):
  return "tag:%s"%self.tag
 
表多对多关系需要定义一张中间表来绑定它们之间的关系。我们通过Table来定义一张中间表(Table需从sqlalchemy中导入)

arctire_tag = Table(
"arctire_tag"       #表名
Base.metadata   #表继承的类
Column(“arctire_id” , Integer , primary_key=True , ForeignKey("arctire.id")      #arctire_id 为字段名
Column("tag_id" , Integer , primary_key=True , ForeignKey("tag.id")   
)

用Table定义好中间表后,我们在两个模型中随便选择一个模型定义relationship属性(在这里,我们以Arctire模型为例,你也可以选择在Tag模型定义),并传入 seconday = "中间表对象”(代码如下所示,红色文字为我们添加的)

class Arctire(Base):  
__tablename__ = "arctire" 
id = Column(Integer , primary_key=True , autoincrement=True)  
name = Column(String(50) , nullable=False)  
tags = relationship("Tag", backref="arctires", secondary=arctire_tag)

最后一步,点击运行。运行无误,然后在mysql命令行工具输入 show create tabel arctire_tag ,如下图所示
sqlalchemy表关系之多对多

代码详解:

PRIMARY KEY("user_id","tag_id")    #user_id,tag_id 字段被封装成复合主键
CONSTRAINT "arctire_tag_ibfk_1" FOREIGN KEY ("user_id”) REFERENCES "arctire” ('id")     #  表示user_id 这个字段引用自arctire表中的id字段
CONSTRAINT "arctire_tag_ibfk_2" FOREIGN KEY ("tag_id”) REFERENCES "tag” ('id")     #  表示tag_id 这个字段引用自tag表中的id字段
出现上方信息,表明表多对多关系创建成功。下面我们添加数据测试一下

arctire1 = Arctire(name = "arctire1")
arctire2 = Arctire(name = "arctire2")

tag1 = Tag(tag = "tag1")
tag2 = Tag(tag = "tag2")

arctire1.tags.append(tag1)
arctire1.tags.append(tag2)

arctire2.tags.append(tag1)
arctire2.tags.append(tag2)

session.add(arctire1)
session.add(arctire2)
session.commit()

然后在命令行工具分别查询arctire,tag,arctire_tag表中的数据
1、select * from arcitre;


2、select * from tag;


3、select * from arctire_tag; (注: user_id1 表示arctire1 ,tag_id 表示tag1......以此类推)


通过上图我们可以发现,数据成功添加入到表中,然后我们从表中查询一下,以此来验证两张表是否成功建立多对多关系。

1、从arctire表中查询所有的标签
arctire = session.query(Arctire).first()
print(arctire.tags)

运行结果如下所示:


2、反之,我们也可以从标签表中查询到标签所被引用的所有文章。


SQLAlchemy中,一对多关系可以通过ForeignKey和relationship来定义。假设我们有两个,一个是User,一个是Post,每个用户可以发多篇文章。我们可以按照以下步骤进行操作: 1. 定义结构 ```python from sqlalchemy import Column, Integer, String, ForeignKey from sqlalchemy.orm import relationship from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String) posts = relationship("Post", back_populates="user") class Post(Base): __tablename__ = 'posts' id = Column(Integer, primary_key=True) title = Column(String) content = Column(String) user_id = Column(Integer, ForeignKey('users.id')) user = relationship("User", back_populates="posts") ``` 在这里,我们使用ForeignKey将Post与User关联起来,并使用relationship定义了之间的关系。在User中,我们使用back_populates参数来指定Post与之关联的属性名,并在Post中定义了一个user_id字段作为外键。 2. 创建Session并查询数据 ```python from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker engine = create_engine('sqlite:///example.db') Session = sessionmaker(bind=engine) session = Session() # 创建用户和文章对象并保存到数据库中 user = User(name='Alice') post1 = Post(title='Title 1', content='Content 1', user=user) post2 = Post(title='Title 2', content='Content 2', user=user) session.add(user) session.commit() # 查询用户及其关联的文章信息 query = session.query(User).options( relationship(User.posts)).filter_by(name='Alice') # 打印查询结果 for user in query.all(): for post in user.posts: print(f"User: {user.name}, Title: {post.title}, Content: {post.content}") ``` 在这个例子中,我们首先创建了一个用户对象和两个文章对象,并通过relationship建立了它们之间的一对多关系。然后我们将它们保存到数据库中。接着,我们使用query.options()函数来指定我们要查询的属性,其中relationship参数设置为User.posts,示我们要查询每个用户的所有文章。最后,我们通过for循环遍历查询结果并打印出来。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值