使用 SQLAlchemy 实现数据库关系:一对一与多对多
在开发应用程序时,我们经常需要在数据库中存储不同类型的数据,并且这些数据之间存在一定的关系。SQLAlchemy 提供了一种优雅的方式来处理这些关系,使得我们在编写 Python 代码时可以更加专注于业务逻辑而不是繁琐的 SQL 语句。本文将介绍如何使用 SQLAlchemy 实现一对一和多对多关系。
在开始之前,请确保安装了必要的 Python 包,包括
SQLAlchemy
和
pymysql
。你可以通过以下命令安装:
1pip install sqlalchemy pymysql
假设我们已经有一个 MySQL 数据库,连接字符串如下:
python
1DB_URI = "mysql+pymysql://root:[email protected]:3306/testsql"
一对一关系 (One-to-One)
一对一关系指的是两个表之间的一条记录只能对应另一条记录。例如,一个用户可以拥有一个电子邮件地址。
实现一对一关系
-
定义模型类
- 使用 SQLAlchemy 的
declarative_base
来定义基础类,然后定义具体的模型类。
-
设置外键
- 在子类中定义外键指向父类的主键。
-
建立关系
- 使用
relationship
来建立表之间的关系。
python
1from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
2from sqlalchemy.ext.declarative import declarative_base
3from sqlalchemy.orm import sessionmaker, relationship
5DB_URI = "mysql+pymysql://root:[email protected]:3306/testsql"
6engine = create_engine(DB_URI)
7Base = declarative_base()
8Session = sessionmaker(bind=engine)
9session = Session()
11class User(Base):
12 __tablename__ = 'users'
13 id = Column(Integer, primary_key=True)
14 name = Column(String(50))
15 email = relationship("Email", uselist=False, back_populates="user")
17 def __repr__(self):
18 return f"<User(name='{self.name}')>"
20class Email(Base):
21 __tablename__ = 'emails'
22 id = Column(Integer, primary_key=True)
23 address = Column(String(50))
24 user_id = Column(Integer, ForeignKey('users.id'))
25 user = relationship("User", back_populates="email")
27 def __repr__(self):
28 return f"<Email(address='{self.address}')>"
30User.email = relationship(
31 "Email",
32 uselist=False,
33 back_populates="user"
36Base.metadata.create_all(engine)
使用一对一关系
现在我们可以创建用户和电子邮件地址,并将它们关联起来。
python
1# 创建用户
2user = User(name='John Doe')
3# 创建电子邮件地址
4email = Email(address='[email protected]')
5# 关联用户和电子邮件
6user.email = email
7# 添加到数据库
8session.add(user)
9session.commit()
多对多关系 (Many-to-Many)
多对多关系是指两个表之间的记录可以对应多个记录。例如,一个教师可以教授多门课程,而一门课程也可以有多个教师。
实现多对多关系
-
定义中间表
- 使用
Table
定义一个中间表,该表至少包含两个外键,分别指向两个需要关联的表。
-
定义模型类
- 定义两个模型类,并使用
relationship
来建立表之间的关系。
python
1from sqlalchemy import create_engine, Column, Integer, String, ForeignKey, Table
2from sqlalchemy.ext.declarative import declarative_base
3from sqlalchemy.orm import sessionmaker, relationship
5DB_URI = "mysql+pymysql://root:[email protected]:3306/testsql"
6engine = create_engine(DB_URI)
7Base = declarative_base()
8Session = sessionmaker(bind=engine)
9session = Session()
11# 创建一个多对多的关系需要创建一个中间表
12teacher_courses = Table(
13 "teacher_courses",
14 Base.metadata,
15 Column("teacher_id", Integer, ForeignKey("teachers.id"), nullable=False, primary_key=True),
16 Column("course_id", Integer, ForeignKey("courses.id"), nullable=False, primary_key=True)
19class Teacher(Base):
20 __tablename__ = 'teachers'
21 id = Column(Integer, primary_key=True)
22 name = Column(String(50))
23 courses = relationship("Course", secondary=teacher_courses, back_populates="teachers")
25 def __repr__(self):
26 return f"<Teacher(name='{self.name}')>"
28class Course(Base):
29 __tablename__ = 'courses'
30 id = Column(Integer, primary_key=True)
31 name = Column(String(50))
32 teachers = relationship("Teacher", secondary=teacher_courses, back_populates="courses")
34 def __repr__(self):
35 return f"<Course(name='{self.name}')>"
37Base.metadata.create_all(engine)
使用多对多关系
创建教师和课程,并将它们关联起来。
python
1# 创建教师
2teacher1 = Teacher(name='Mr. Smith')
3teacher2 = Teacher(name='Ms. Johnson')
5# 创建课程
6course1 = Course(name='Mathematics')
7course2 = Course(name='Physics')
9# 关联教师和课程
10teacher1.courses = [course1, course2]
11teacher2.courses = [course1]
13# 添加到数据库
14session.add_all([teacher1, teacher2])
15session.commit()
你可以轻松地查询关系。
python
1# 查询教师及其教授的课程
2teacher = session.query(Teacher).filter_by(name='Mr. Smith').first()
3print(teacher.courses)
5# 查询课程及其对应的教师
6course = session.query(Course).filter_by(name='Mathematics').first()
7print(course.teachers)
以上就是使用 SQLAlchemy 实现一对一和多对多关系的基本方法。希望这篇文章能帮助你更好地理解和使用 SQLAlchemy 来管理数据库中的关系。
有时候,我们在使用
SQLAlchemy
操作某些
表
的时候,需要使用外键
关系
来实现
一对多
或者多对多的
关系
引用,以及对多
表
的联合查询,有序列的uuid值或者自增id值,字符串的分拆等常见处理操作。
1、在
SQLAlchemy
中定义具有嵌套 children
关系
的
表
要在
SQLAlchemy
中定义具有嵌套 children
关系
的
表
,如
表
中包含 id 和 pid 字段,可以使用 relatio...
今天我们就讲讲
sqlalchemy
最后一种
关系
:
一对一
首先,我们先创建user(父
表
)、arctire(子
表
)两张
表
,代码如下:#父
表
class User(Base): __tablename__ = "user" id = Column(Integer , primary_key=True , autoincrement=True) name = Column(String...
sqlalchemy
表
之间
的
关系
有三种:1、多对多 2、
一对多
3、
一对一
下面就讲讲
sqlalchemy
表
之间
如何
建立
多对多
关系
。 首先,我们把两个需要做多对多
关系
的模型定义出来,这里以Arctire,Tag模型为例(示例代码如下)class Arctire(Base): __tablename__ = "arctire" id = Column(Integer , prima...
最为常见的
关系
就是
一对多
的
关系
。因为
关系
在它们
建立
之前就已经声明,您可以使用 字符串来指代还没有创建的类(例如如果Person定义了一个到Article的
关系
,而Article在文件的后面才会声明)。
关系
使用relationship()函数
表
示。然而外键必须用类
sqlalchemy
.schema.ForeignKey来单独声明:
class Person(db.Model):
id = db.Column(db.Integer, primary_key=True)
SQLAlchemy
“采用简单的
Python
语言,为高效和高性能的
数据库
访问设计,实现了完整的企业级持久模型”。
SQLAlchemy
的理念是,
SQL
数据库
的量级和性能重要于对象集合;而对象集合的抽象又重要于
表
和行。因此,
SQLAlchemy
采用了类似于Java里Hibernate的数据映射模型,而不是其他ORM框架采用的Active Record模型。
其中author_id = db.Column(db.Integer, db.ForeignKey("user.id"))这一句通过外键的方式使得Article
表
可以访问user
表
中的id项。在视图函数中,我们创建好articles和user实例后,通过articles.author=user进行绑定。比如我们要创建一张用户
表
和文章
表
,因为用户与文章是
一对多
的
关系
(一个用户可以有多篇文章,一篇文章往往是一个用户所写)。可以看见成功创建了两个
表
,并且author_id和user
表
的id是一致的。
SQLAlchemy
是一个强大的
Python
ORM(对象
关系
映射)库,它允许我们将
数据库
表
映射到
Python
对象,并提供了丰富的
关系
模型来处理不同类型的
关系
,包括
一对一
关系
。在本文中,我们将深入探讨
SQLAlchemy
中
表
一对一
关系
的概念,以及如何在模型中定义和使用这种
关系
。
一对一
关系
是
数据库
中两个
表
之间
的
关系
,其中一个
表
的每个记录对应另一个
表
的一个记录,而且每个记录在另一个
表
中只有一个关联项。