我面临着一种我在技术上无法理解的行为。
假设我有一个如下所示的数据模型。
class MastoList(db.Model):
__tablename__ = 'mastolist'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255), nullable=False)
list_id = db.Column(db.String(255), nullable=False)
base_url = db.Column(db.String(255), nullable=False)
max_id = db.Column(db.String(100), nullable=False, default='0')
updated_at = db.Column(db.DateTime, nullable=True)
class Toot(db.Model):
id = db.Column(db.String(255), primary_key=True)
list_id = db.Column(db.Integer, db.ForeignKey('mastolist.id'), nullable=False)
account = db.Column(db.String(255))
account_displayname = db.Column(db.String(255))
created_at = db.Column(db.DateTime, default=datetime.utcnow)
uri = db.Column(db.String(255), unique=True, nullable=False)
content = db.Column(db.Text, nullable=True)
生成的数据库结构如下所示。
CREATE TABLE mastolist (
id INTEGER NOT NULL,
name VARCHAR(255) NOT NULL,
list_id VARCHAR(255) NOT NULL,
base_url VARCHAR(255) NOT NULL,
max_id VARCHAR(100) NOT NULL, updated_at DATETIME,
PRIMARY KEY (id)
)
CREATE TABLE toot (
id VARCHAR(255) NOT NULL,
list_id INTEGER NOT NULL,
account VARCHAR(255),
account_displayname VARCHAR(255),
created_at DATETIME,
uri VARCHAR(255) NOT NULL,
content TEXT,
reblogged BOOLEAN NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY(list_id) REFERENCES mastolist (id),
UNIQUE (uri)
)
存储数据的数据库包含
MastoList
的一行,其中 id
= 1。Toot
包含多行都设置了 list_id
= 1。如果我尝试使用数据库浏览器从 MastoList
中删除该行SQLite 我收到预期的 FOREIGN KEY constraint failed
错误。
尝试使用以下代码删除该行,不会出现任何错误。
session = Session(db)
masto_list = session.execute(select(MastoList).filter(MastoList.id == id)).scalar_one()
session.delete(masto_list)
session.commit()
之后
Toot
中的所有行的 list_id
仍然为 1。
只要我添加
toots = db.Relationship('Toot', backref='MastoList')
到
MastoList
的模型,当尝试使用我的代码删除行时,我也得到了预期的外键错误。
任何人都可以解释为什么可以使用我的代码删除行,这意味着数据库约束被简单地忽略?
为了向后兼容,SQLite 默认情况下不启用外键强制。你可以用
PRAGMA foreign_keys = ON;
启用它。那么如果 SQLAlchemy 不强制执行 FK 本身(
backref
选项启用),您应该会收到错误。