外键及其四种约束
-
外键
在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)
外键约束有以下几项:
- 1、RESTRICT:父表数据被删除,会阻止删除。默认就是这一项。
- 2、NO ACTION:在MySQL中,同RESTRICT。
- 3、CASCADE:级联删除。
- 4、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_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="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',uselist=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第一个参数是表示的是连接表的外键名,第二个参数表示这个外键的类型,第三个参数表示要外键的表名和字段。
-