我一直在尋找在SQLAlchemy中使用PyMySQL驅動程序和MariaDB 10.0在數據庫中使用InnoDB的下面的UsersAccessMapping模型中實現CONSTRAINT FOREIGN KEY ON DELETE CASCADE的方法。Flask-SQLAlchemy如何在MySQL(InnoDB)中執行級聯約束外鍵?
Python = 3.5.2
SQLAlchemy = 1.1.13
Flask-SQLAlchemy = 2.2
的SQL:
CREATE TABLE Users (
UserID int AUTO_INCREMENT,
Name varchar(200) NOT NULL,
Email varchar(200),
Username varchar(200) NOT NULL,
Password text NOT NULL,
Created datetime,
Updated datetime,
PRIMARY KEY (UserID)
);
CREATE TABLE UsersAccessLevels (
UsersAccessLevelID int AUTO_INCREMENT,
LevelName varchar(100) NOT NULL,
AccessDescription text,
PRIMARY KEY (UsersAccessLevelID)
);
CREATE TABLE UsersAccessMapping (
UsersAccessMappingID int AUTO_INCREMENT,
UserID int NOT NULL,
UsersAccessLevelID int NOT NULL,
PRIMARY KEY (UsersAccessMappingID),
CONSTRAINT fk_useraccess FOREIGN KEY (UserID)
REFERENCES Users(UserID) ON DELETE CASCADE,
CONSTRAINT fk_useraccess_level FOREIGN KEY (UsersAccessLevelID)
REFERENCES UsersAccessLevels(UsersAccessLevelID) ON DELETE CASCADE
);
我在我現在的models.py
什麼:
from app import db
class Users(db.Model):
"""All users' information is stored here"""
__tablename__ = "Users"
UserID = db.Column(db.Integer(), primary_key=True)
Name = db.Column(db.String(200), nullable=False)
Email = db.Column(db.String(200))
Username = db.Column(db.String(200), nullable=False)
Password = db.Column(db.Text, nullable=False)
Created = db.Column(db.DateTime)
Updated = db.Column(db.DateTime)
class UsersAccessLevels(db.Model):
"""This defines the various access levels users can have"""
__tablename__ = "UsersAccessLevels"
UsersAccessLevelID = db.Column(db.Integer, primary_key=True)
LevelName = db.Column(db.String(100), nullable=False)
AccessDescription = db.Column(db.Text)
class UsersAccessMapping(db.Model):
"""Each users' access level is defined here"""
__tablename__ = "UsersAccessMapping"
UsersAccessMappingID = db.Column(db.Integer, primary_key=True)
UserID = db.Column(db.Integer, nullable=False)
UsersAccessLevelID = db.Column(db.Integer, nullable=False)
__table_args__ = (
db.ForeignKeyConstraint(
["fk_useraccess", "fk_useraccess_level"],
["Users.UserID", "UsersAccessLevels.UsersAccessLevelID"],
ondelete="CASCADE"
)
)
也有一些是錯誤的table_args語法,但我一直沒能找到它應該如何的任何例子。我發現一個非常相似,但第三個參數是一個空字典。不過,我想使用ondelete =「CASCADE」。那將如何增加?
當運行python3 manage.py db init
,它拋出這樣的:
File "/srv/vortech-backend/venv/lib/python3.5/site-packages/sqlalchemy/ext/declarative/base.py", line 196, in _scan_attributes
"__table_args__ value must be a tuple, "
sqlalchemy.exc.ArgumentError: __table_args__ value must be a tuple, dict, or None
我試圖改變ondelete="cascade"
到字典{"ondelete": "cascade"}
,但這並不能工作。它給出了與上面相同的錯誤。
更新: 的問題是,ondelete應該是元組之外,就像這樣:
__table_args__ = (
db.ForeignKeyConstraint(
["fk_useraccess", "fk_useraccess_level"],
["Users.UserID", "UsersAccessLevels.UsersAccessLevelID"]
),
ondelete="CASCADE"
)
然而,這種變化仍然存在語法錯誤,如ondelete="CASCADE"
不定義。它更改爲一個字典{"ondelete": "cascade"}
拋出這個:
File "/srv/vortech-backend/venv/lib/python3.5/site-packages/sqlalchemy/sql/base.py", line 282, in _validate_dialect_kwargs
"named <dialectname>_<argument>, got '%s'" % k)
TypeError: Additional arguments should be named <dialectname>_<argument>, got 'ondelete'
有趣的是,在http://docs.sqlalchemy.org/en/latest/core/constraints.html#on-update-and-on-delete,它顯示了我最初的方式(不起作用)。 –
您已經鏈接到Core docs,瞭解如何將外鍵約束作爲參數傳遞給「Table」構造函數。它與你有的聲明類定義有很大的不同,如果傳遞這樣的話(就像錯誤說的那樣),它應該有一個序列或參數映射爲'__table_args__'。通常會傳遞一個元組或字典。您已經傳遞了一個'ForeignKeyConstraint',因爲您忘記在它後面添加逗號,所以您在冗餘括號中有一個表達式。而ondelete關鍵字參數將屬於'ForeignKeyConstraint'調用中,而不是它的外部。 –
第一次嘗試還有很多錯誤,例如試圖爲2個不同的表創建複合外鍵。 –