本章主题
关键词
外键
在 Mysql 中,外键可以让表之间的关系更加紧密。⽽ SQLAlchemy 同样也支持外键。
通过 ForeignKey 类来实现,并且可以指定表的外键约束:
class Article(Base):
__tablename__ = 'article'
id = Column(Integer,primary_key=True,autoincrement=True)
title = Column(String(50),nullable=False)
content = Column(Text,nullable=False)
uid = Column(Integer,ForeignKey('user.id'))
def __repr__(self):
return "<Article(title:%s)>" % self.title
class User(Base):
__tablename__ = 'user'
id = Column(Integer,primary_key=True,autoincrement=True)
username = Column(String(50),nullable=False)
外键约束有以下几项:
RESTRICT
:父表数据被删除,会阻⽌删除。默认就是这⼀项。NO ACTION
:在MySQL中,同RESTRICT
。CASCADE
:级联删除。SET NULL
:⽗表数据被删除,⼦表数据会设置为NULL
。
表关系:
表之间的关系存在三种:⼀对⼀ 、⼀对多 、多对多 。⽽ SQLAlchemy 中的 ORM 也可以模拟这三种关系。因为⼀对⼀其实在 SQLAlchemy 中底层是通过⼀对多的⽅式模拟的。
一对多
拿之前的 User 表为例,假如现在要添加⼀个功能,要保存⽤户的邮箱帐号,并 且邮箱帐号可以有多个,这时候就必须创建⼀个新的表,⽤来存储⽤户的邮箱,然后通过 user.id
来作为外键进⾏引⽤:
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
class Address(Base):
__tablename__ = 'address'
id = Column(Integer,primary_key=True)
email_address = Column(String,nullable=False)
user_id = Column(Integer,ForeignKey('users.id'))
user = relationship('User',backref="addresses")
def __repr__(self):
return "<Address(email_address='%s')>" % self.email_addre ss
class User(Base):
__tablename__ = 'users'
id = Column(Integer,primary_key=True)
name = Column(String(50))
fullname = Column(String(50))
password = Column(String(100))
addresses = relationship("Address",backref="user")
一对一
⼀对⼀其实就是⼀对多的特殊情况,从以上的⼀对多例⼦中不难发现,⼀对应 的是 User 表,⽽多对应的是 Address
,也就是说⼀个 User 对象有多个 Address
。因此要将⼀对多转换成⼀对⼀,只要设置⼀个 User 对象对应⼀个 Address
对象即可:
class User(Base):
__tablename__ = 'users'
id = Column(Integer,primary_key=True)
name = Column(String(50))
fullname = Column(String(50))
password = Column(String(100))
addresses = relationship("Address",backref='addresses',uselis t=False)
class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer,primary_key=True)
email_address = Column(String(50))
user_id = Column(Integer,ForeignKey('users.id')
user = relationship('Address',backref='user')
从以上例⼦可以看到,只要在 User 表中的 addresses
字段上添加 uselist = False
就可以达到⼀对⼀的效果
多对多
多对多需要⼀个中间表来作为连接,同理在 sqlalchemy
中的 orm
也需要⼀个中间表。假如现在有⼀个 Teacher表 和⼀个 Classes表,即⽼师和班级,⼀个⽼师可以教多个班级,⼀个班级有多个⽼师,是⼀种典型的多对多的关系,那 么通过 sqlalchemy
的 ORM 的实现⽅式:
association_table = Table(
'teacher_classes',
Base.metadata,
Column('teacher_id',Integer,ForeignKey('teacher.id')),
Column('classes_id',Integer,ForeignKey('classes.id'))
)
class Teacher(Base):
__tablename__ = 'teacher'
id = Column(Integer,primary_key=True)
tno = Column(String(10))
name = Column(String(50))
age = Column(Integer)
classes = relationship('Classes',secondary=association_table, backref='teachers')
class Classes(Base):
__tablename__ = 'classes'
id = Column(Integer,primary_key=True)
cno = Column(String(10))
name = Column(String(50))
teachers = relationship('Teacher',secondary=association_table ,backref='classes')
要创建⼀个多对多的关系表,⾸先需要⼀个中间表,通过 Table 来创建⼀个中 间表。上例中 第⼀个 参数 teacher_classes
代表的是中间表的表名,第二个 参数是 Base 的元类,第三 个和 第四 个参数就是要连接的两个表,其中 Column 第⼀个参数是表示的是连接表的外键名,第⼆个参数表示这个外键的类型,第三个参数表示要外键的表名和字段。
总结小便条
本篇文章主要讲了以下几点内容:
本章回顾暂时就到这了,如果还有点晕,那就把文章里所有引用的案例代码再敲几遍吧。拜拜~