问题
I have two related tables namely users
and roles
and the relationship between them is many-to-many, so another association table userroles
also exists.
The userroles
table keeps track of the associated users
and roles
rows using foreign keys. For the foreign keys the ondelete
parameter is set to "CASCADE"
to get rid of the association row if any of the associated elements are being deleted.
This is my setup:
import sqlalchemy as sa
engine = sa.create_engine("sqlite:///:memory:", echo=True)
metadata = sa.MetaData()
userroles = sa.Table(
"userroles",
metadata,
sa.Column("user_id", sa.Integer, sa.ForeignKey("users.id", ondelete="CASCADE")),
sa.Column("role_id", sa.Integer, sa.ForeignKey("roles.id", ondelete="CASCADE")),
)
users = sa.Table(
"users",
metadata,
sa.Column("id", sa.Integer, primary_key=True),
sa.Column("name", sa.String),
)
roles = sa.Table(
"roles",
metadata,
sa.Column("id", sa.Integer, primary_key=True),
sa.Column("name", sa.String),
)
metadata.create_all(engine)
conn = engine.connect()
conn.execute(users.insert().values(name="Joe"))
conn.execute(roles.insert().values(name="Admin"))
conn.execute(roles.insert().values(name="User"))
conn.execute(userroles.insert().values(user_id=1, role_id=1))
However when I delete the Admin
role which has the unique id of 1
, the associated row is not being deleted from the userroles
table. Why?
What am I missing here?
回答1:
Okay it seems like you need to enforce foreign keys for sqlite. So based on this answer one should do:
from sqlalchemy import event
from sqlalchemy.engine import Engine
from sqlite3 import Connection as SQLite3Connection
@event.listens_for(Engine, "connect")
def _set_sqlite_pragma(dbapi_connection, connection_record):
if isinstance(dbapi_connection, SQLite3Connection):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON;")
cursor.close()
来源:https://stackoverflow.com/questions/57726047/sqlalchemy-expression-language-and-sqlites-on-delete-cascade